diff options
Diffstat (limited to 'scene')
419 files changed, 4868 insertions, 6923 deletions
diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp index 9d02408641..917ced5feb 100644 --- a/scene/2d/animated_sprite.cpp +++ b/scene/2d/animated_sprite.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -35,6 +35,7 @@ #define NORMAL_SUFFIX "_normal" +#ifdef TOOLS_ENABLED Dictionary AnimatedSprite::_edit_get_state() const { Dictionary state = Node2D::_edit_get_state(); state["offset"] = offset; @@ -72,6 +73,7 @@ bool AnimatedSprite::_edit_use_rect() const { t = frames->get_frame(animation, frame); return t.is_valid(); } +#endif Rect2 AnimatedSprite::get_anchorable_rect() const { return _get_rect(); diff --git a/scene/2d/animated_sprite.h b/scene/2d/animated_sprite.h index 3192d44678..cd00a4e181 100644 --- a/scene/2d/animated_sprite.h +++ b/scene/2d/animated_sprite.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -156,6 +156,7 @@ protected: virtual void _validate_property(PropertyInfo &property) const; public: +#ifdef TOOLS_ENABLED virtual Dictionary _edit_get_state() const; virtual void _edit_set_state(const Dictionary &p_state); @@ -164,6 +165,7 @@ public: virtual bool _edit_use_pivot() const; virtual Rect2 _edit_get_rect() const; virtual bool _edit_use_rect() const; +#endif virtual Rect2 get_anchorable_rect() const; diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp index 66a1318cb7..8302ba5336 100644 --- a/scene/2d/area_2d.cpp +++ b/scene/2d/area_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/area_2d.h b/scene/2d/area_2d.h index 2d1527810e..6d9386c535 100644 --- a/scene/2d/area_2d.h +++ b/scene/2d/area_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp index 932af469d0..4f0f681a01 100644 --- a/scene/2d/audio_stream_player_2d.cpp +++ b/scene/2d/audio_stream_player_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/audio_stream_player_2d.h b/scene/2d/audio_stream_player_2d.h index ffa3d4edb4..86e931b3c6 100644 --- a/scene/2d/audio_stream_player_2d.h +++ b/scene/2d/audio_stream_player_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/back_buffer_copy.cpp b/scene/2d/back_buffer_copy.cpp index 4a4bc4410f..faeb6b7169 100644 --- a/scene/2d/back_buffer_copy.cpp +++ b/scene/2d/back_buffer_copy.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -50,6 +50,7 @@ void BackBufferCopy::_update_copy_mode() { } } +#ifdef TOOLS_ENABLED Rect2 BackBufferCopy::_edit_get_rect() const { return rect; @@ -58,6 +59,7 @@ Rect2 BackBufferCopy::_edit_get_rect() const { bool BackBufferCopy::_edit_use_rect() const { return true; } +#endif Rect2 BackBufferCopy::get_anchorable_rect() const { diff --git a/scene/2d/back_buffer_copy.h b/scene/2d/back_buffer_copy.h index 52b0c016cc..4b26bf1bdc 100644 --- a/scene/2d/back_buffer_copy.h +++ b/scene/2d/back_buffer_copy.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -53,8 +53,10 @@ protected: static void _bind_methods(); public: +#ifdef TOOLS_ENABLED Rect2 _edit_get_rect() const; virtual bool _edit_use_rect() const; +#endif void set_rect(const Rect2 &p_rect); Rect2 get_rect() const; diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index 3e8902314c..e9f8c5dff2 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h index bb3c76b30c..04b5260444 100644 --- a/scene/2d/camera_2d.h +++ b/scene/2d/camera_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index fa23e3fd39..5631aa3355 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -351,7 +351,7 @@ CanvasItemMaterial::~CanvasItemMaterial() { } /////////////////////////////////////////////////////////////////// - +#ifdef TOOLS_ENABLED bool CanvasItem::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { if (_edit_use_rect()) { return _edit_get_rect().has_point(p_point); @@ -363,6 +363,7 @@ bool CanvasItem::_edit_is_selected_on_click(const Point2 &p_point, double p_tole Transform2D CanvasItem::_edit_get_transform() const { return Transform2D(_edit_get_rotation(), _edit_get_position() + _edit_get_pivot()); } +#endif bool CanvasItem::is_visible_in_tree() const { @@ -1121,9 +1122,10 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("_toplevel_raise_self"), &CanvasItem::_toplevel_raise_self); ClassDB::bind_method(D_METHOD("_update_callback"), &CanvasItem::_update_callback); + +#ifdef TOOLS_ENABLED ClassDB::bind_method(D_METHOD("_edit_set_state", "state"), &CanvasItem::_edit_set_state); ClassDB::bind_method(D_METHOD("_edit_get_state"), &CanvasItem::_edit_get_state); - ClassDB::bind_method(D_METHOD("_edit_set_position", "position"), &CanvasItem::_edit_set_position); ClassDB::bind_method(D_METHOD("_edit_get_position"), &CanvasItem::_edit_get_position); ClassDB::bind_method(D_METHOD("_edit_set_scale", "scale"), &CanvasItem::_edit_set_scale); @@ -1138,6 +1140,7 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("_edit_get_pivot"), &CanvasItem::_edit_get_pivot); ClassDB::bind_method(D_METHOD("_edit_use_pivot"), &CanvasItem::_edit_use_pivot); ClassDB::bind_method(D_METHOD("_edit_get_transform"), &CanvasItem::_edit_get_transform); +#endif ClassDB::bind_method(D_METHOD("get_canvas_item"), &CanvasItem::get_canvas_item); diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index e51ee601e2..8814d99edd 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -249,7 +249,7 @@ public: }; /* EDITOR */ - +#ifdef TOOLS_ENABLED // Select the node virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; @@ -282,6 +282,7 @@ public: virtual Point2 _edit_get_pivot() const { return Point2(); }; virtual Transform2D _edit_get_transform() const; +#endif /* VISIBILITY */ diff --git a/scene/2d/canvas_modulate.cpp b/scene/2d/canvas_modulate.cpp index 009d664462..25db434918 100644 --- a/scene/2d/canvas_modulate.cpp +++ b/scene/2d/canvas_modulate.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/canvas_modulate.h b/scene/2d/canvas_modulate.h index 101abb4f00..ada6e27760 100644 --- a/scene/2d/canvas_modulate.h +++ b/scene/2d/canvas_modulate.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp index 228b67990c..3e9e63a7f0 100644 --- a/scene/2d/collision_object_2d.cpp +++ b/scene/2d/collision_object_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -46,8 +46,6 @@ void CollisionObject2D::_notification(int p_what) { else Physics2DServer::get_singleton()->body_set_state(rid, Physics2DServer::BODY_STATE_TRANSFORM, global_transform); - last_transform = global_transform; - RID space = get_world_2d()->get_space(); if (area) { Physics2DServer::get_singleton()->area_set_space(rid, space); @@ -73,19 +71,17 @@ void CollisionObject2D::_notification(int p_what) { } break; case NOTIFICATION_TRANSFORM_CHANGED: { - Transform2D global_transform = get_global_transform(); - - if (only_update_transform_changes && global_transform == last_transform) { + if (only_update_transform_changes) { return; } + Transform2D global_transform = get_global_transform(); + if (area) Physics2DServer::get_singleton()->area_set_transform(rid, global_transform); else Physics2DServer::get_singleton()->body_set_state(rid, Physics2DServer::BODY_STATE_TRANSFORM, global_transform); - last_transform = global_transform; - } break; case NOTIFICATION_EXIT_TREE: { diff --git a/scene/2d/collision_object_2d.h b/scene/2d/collision_object_2d.h index 4e7d01c8e6..8874f61bb7 100644 --- a/scene/2d/collision_object_2d.h +++ b/scene/2d/collision_object_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -67,7 +67,6 @@ class CollisionObject2D : public Node2D { int total_subshapes; Map<uint32_t, ShapeData> shapes; - Transform2D last_transform; bool only_update_transform_changes; //this is used for sync physics in KinematicBody protected: diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp index bb144dda96..d9cc94c6eb 100644 --- a/scene/2d/collision_polygon_2d.cpp +++ b/scene/2d/collision_polygon_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -169,8 +169,8 @@ void CollisionPolygon2D::_notification(int p_what) { Vector<Vector2> pts; float tsize = 8; pts.push_back(line_to + (Vector2(0, tsize))); - pts.push_back(line_to + (Vector2(0.707 * tsize, 0))); - pts.push_back(line_to + (Vector2(-0.707 * tsize, 0))); + pts.push_back(line_to + (Vector2(Math_SQRT12 * tsize, 0))); + pts.push_back(line_to + (Vector2(-Math_SQRT12 * tsize, 0))); Vector<Color> cols; for (int i = 0; i < 3; i++) cols.push_back(dcol); @@ -227,6 +227,7 @@ CollisionPolygon2D::BuildMode CollisionPolygon2D::get_build_mode() const { return build_mode; } +#ifdef TOOLS_ENABLED Rect2 CollisionPolygon2D::_edit_get_rect() const { return aabb; @@ -240,6 +241,7 @@ bool CollisionPolygon2D::_edit_is_selected_on_click(const Point2 &p_point, doubl return Geometry::is_point_in_polygon(p_point, Variant(polygon)); } +#endif String CollisionPolygon2D::get_configuration_warning() const { diff --git a/scene/2d/collision_polygon_2d.h b/scene/2d/collision_polygon_2d.h index b88679f15b..d8dfec8fd2 100644 --- a/scene/2d/collision_polygon_2d.h +++ b/scene/2d/collision_polygon_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -67,16 +67,18 @@ protected: static void _bind_methods(); public: +#ifdef TOOLS_ENABLED + virtual Rect2 _edit_get_rect() const; + virtual bool _edit_use_rect() const; + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; +#endif + void set_build_mode(BuildMode p_mode); BuildMode get_build_mode() const; void set_polygon(const Vector<Point2> &p_polygon); Vector<Point2> get_polygon() const; - virtual Rect2 _edit_get_rect() const; - virtual bool _edit_use_rect() const; - virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; - virtual String get_configuration_warning() const; void set_disabled(bool p_disabled); diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp index f79d79d039..eace4c64fc 100644 --- a/scene/2d/collision_shape_2d.cpp +++ b/scene/2d/collision_shape_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -134,8 +134,8 @@ void CollisionShape2D::_notification(int p_what) { Vector<Vector2> pts; float tsize = 8; pts.push_back(line_to + (Vector2(0, tsize))); - pts.push_back(line_to + (Vector2(0.707 * tsize, 0))); - pts.push_back(line_to + (Vector2(-0.707 * tsize, 0))); + pts.push_back(line_to + (Vector2(Math_SQRT12 * tsize, 0))); + pts.push_back(line_to + (Vector2(-Math_SQRT12 * tsize, 0))); Vector<Color> cols; for (int i = 0; i < 3; i++) cols.push_back(draw_col); diff --git a/scene/2d/collision_shape_2d.h b/scene/2d/collision_shape_2d.h index 26c61f47bd..80bea0a979 100644 --- a/scene/2d/collision_shape_2d.h +++ b/scene/2d/collision_shape_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index 372d8f614b..acb1b0b5a0 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,7 +29,7 @@ /*************************************************************************/ #include "cpu_particles_2d.h" - +#include "core/core_string_names.h" #include "scene/2d/canvas_item.h" #include "scene/2d/particles_2d.h" #include "scene/resources/particles_material.h" @@ -169,10 +169,20 @@ void CPUParticles2D::_update_mesh_texture() { vertices.push_back(-tex_size * 0.5 + Vector2(tex_size.x, tex_size.y)); vertices.push_back(-tex_size * 0.5 + Vector2(0, tex_size.y)); PoolVector<Vector2> uvs; - uvs.push_back(Vector2(0, 0)); - uvs.push_back(Vector2(1, 0)); - uvs.push_back(Vector2(1, 1)); - uvs.push_back(Vector2(0, 1)); + AtlasTexture *atlas_texure = Object::cast_to<AtlasTexture>(*texture); + if (atlas_texure && atlas_texure->get_atlas().is_valid()) { + Rect2 region_rect = atlas_texure->get_region(); + Size2 atlas_size = atlas_texure->get_atlas()->get_size(); + uvs.push_back(Vector2(region_rect.position.x / atlas_size.x, region_rect.position.y / atlas_size.y)); + uvs.push_back(Vector2((region_rect.position.x + region_rect.size.x) / atlas_size.x, region_rect.position.y / atlas_size.y)); + uvs.push_back(Vector2((region_rect.position.x + region_rect.size.x) / atlas_size.x, (region_rect.position.y + region_rect.size.y) / atlas_size.y)); + uvs.push_back(Vector2(region_rect.position.x / atlas_size.x, (region_rect.position.y + region_rect.size.y) / atlas_size.y)); + } else { + uvs.push_back(Vector2(0, 0)); + uvs.push_back(Vector2(1, 0)); + uvs.push_back(Vector2(1, 1)); + uvs.push_back(Vector2(0, 1)); + } PoolVector<Color> colors; colors.push_back(Color(1, 1, 1, 1)); colors.push_back(Color(1, 1, 1, 1)); @@ -198,12 +208,29 @@ void CPUParticles2D::_update_mesh_texture() { } void CPUParticles2D::set_texture(const Ref<Texture> &p_texture) { + if (p_texture == texture) + return; + + if (texture.is_valid()) + texture->disconnect(CoreStringNames::get_singleton()->changed, this, "_texture_changed"); texture = p_texture; + + if (texture.is_valid()) + texture->connect(CoreStringNames::get_singleton()->changed, this, "_texture_changed"); + update(); _update_mesh_texture(); } +void CPUParticles2D::_texture_changed() { + + if (texture.is_valid()) { + update(); + _update_mesh_texture(); + } +} + Ref<Texture> CPUParticles2D::get_texture() const { return texture; @@ -294,15 +321,6 @@ float CPUParticles2D::get_spread() const { return spread; } -void CPUParticles2D::set_flatness(float p_flatness) { - - flatness = p_flatness; -} -float CPUParticles2D::get_flatness() const { - - return flatness; -} - void CPUParticles2D::set_param(Parameter p_param, float p_value) { ERR_FAIL_INDEX(p_param, PARAM_MAX); @@ -422,7 +440,7 @@ bool CPUParticles2D::get_particle_flag(Flags p_flag) const { } void CPUParticles2D::set_emission_shape(EmissionShape p_shape) { - + ERR_FAIL_INDEX(p_shape, EMISSION_SHAPE_MAX); emission_shape = p_shape; _change_notify(); } @@ -772,6 +790,9 @@ void CPUParticles2D::_particles_process(float p_delta) { p.base_color = emission_colors.get(random_idx); } } break; + case EMISSION_SHAPE_MAX: { // Max value for validity check. + break; + } } if (!local_coords) { @@ -1166,7 +1187,6 @@ void CPUParticles2D::convert_from_particles(Node *p_particles) { Vector3 dir = material->get_direction(); set_direction(Vector2(dir.x, dir.y)); set_spread(material->get_spread()); - set_flatness(material->get_flatness()); set_color(material->get_color()); @@ -1280,9 +1300,6 @@ void CPUParticles2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_spread", "degrees"), &CPUParticles2D::set_spread); ClassDB::bind_method(D_METHOD("get_spread"), &CPUParticles2D::get_spread); - ClassDB::bind_method(D_METHOD("set_flatness", "amount"), &CPUParticles2D::set_flatness); - ClassDB::bind_method(D_METHOD("get_flatness"), &CPUParticles2D::get_flatness); - ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &CPUParticles2D::set_param); ClassDB::bind_method(D_METHOD("get_param", "param"), &CPUParticles2D::get_param); @@ -1325,6 +1342,7 @@ void CPUParticles2D::_bind_methods() { ClassDB::bind_method(D_METHOD("convert_from_particles", "particles"), &CPUParticles2D::convert_from_particles); ClassDB::bind_method(D_METHOD("_update_render_thread"), &CPUParticles2D::_update_render_thread); + ClassDB::bind_method(D_METHOD("_texture_changed"), &CPUParticles2D::_texture_changed); ADD_GROUP("Emission Shape", "emission_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points"), "set_emission_shape", "get_emission_shape"); @@ -1338,7 +1356,6 @@ void CPUParticles2D::_bind_methods() { ADD_GROUP("Direction", ""); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "direction"), "set_direction", "get_direction"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "spread", PROPERTY_HINT_RANGE, "0,180,0.01"), "set_spread", "get_spread"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "flatness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_flatness", "get_flatness"); ADD_GROUP("Gravity", ""); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "gravity"), "set_gravity", "get_gravity"); ADD_GROUP("Initial Velocity", "initial_"); @@ -1416,6 +1433,7 @@ void CPUParticles2D::_bind_methods() { BIND_ENUM_CONSTANT(EMISSION_SHAPE_RECTANGLE); BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINTS); BIND_ENUM_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS); + BIND_ENUM_CONSTANT(EMISSION_SHAPE_MAX); } CPUParticles2D::CPUParticles2D() { @@ -1448,7 +1466,6 @@ CPUParticles2D::CPUParticles2D() { set_direction(Vector2(1, 0)); set_spread(45); - set_flatness(0); set_param(PARAM_INITIAL_LINEAR_VELOCITY, 0); set_param(PARAM_ANGULAR_VELOCITY, 0); set_param(PARAM_ORBIT_VELOCITY, 0); diff --git a/scene/2d/cpu_particles_2d.h b/scene/2d/cpu_particles_2d.h index 47b4568dd4..d59b94bcbb 100644 --- a/scene/2d/cpu_particles_2d.h +++ b/scene/2d/cpu_particles_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -75,6 +75,7 @@ public: EMISSION_SHAPE_RECTANGLE, EMISSION_SHAPE_POINTS, EMISSION_SHAPE_DIRECTED_POINTS, + EMISSION_SHAPE_MAX }; private: @@ -153,7 +154,6 @@ private: Vector2 direction; float spread; - float flatness; float parameters[PARAM_MAX]; float randomness[PARAM_MAX]; @@ -186,6 +186,8 @@ private: void _set_redraw(bool p_redraw); + void _texture_changed(); + protected: static void _bind_methods(); void _notification(int p_what); @@ -242,9 +244,6 @@ public: void set_spread(float p_spread); float get_spread() const; - void set_flatness(float p_flatness); - float get_flatness() const; - void set_param(Parameter p_param, float p_value); float get_param(Parameter p_param) const; diff --git a/scene/2d/joints_2d.cpp b/scene/2d/joints_2d.cpp index 847d08b025..656ff45654 100644 --- a/scene/2d/joints_2d.cpp +++ b/scene/2d/joints_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/joints_2d.h b/scene/2d/joints_2d.h index a3951eb9d2..f1750e56b6 100644 --- a/scene/2d/joints_2d.h +++ b/scene/2d/joints_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp index 7b3eab175a..1bffaf8084 100644 --- a/scene/2d/light_2d.cpp +++ b/scene/2d/light_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,6 +33,7 @@ #include "core/engine.h" #include "servers/visual_server.h" +#ifdef TOOLS_ENABLED Dictionary Light2D::_edit_get_state() const { Dictionary state = Node2D::_edit_get_state(); state["offset"] = get_texture_offset(); @@ -68,6 +69,7 @@ Rect2 Light2D::_edit_get_rect() const { bool Light2D::_edit_use_rect() const { return !texture.is_null(); } +#endif Rect2 Light2D::get_anchorable_rect() const { if (texture.is_null()) @@ -187,6 +189,10 @@ float Light2D::get_energy() const { void Light2D::set_texture_scale(float p_scale) { _scale = p_scale; + // Avoid having 0 scale values, can lead to errors in physics and rendering. + if (_scale == 0) { + _scale = CMP_EPSILON; + } VS::get_singleton()->canvas_light_set_scale(canvas_light, _scale); item_rect_changed(); } diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h index b1940f64cd..65db5c6ee6 100644 --- a/scene/2d/light_2d.h +++ b/scene/2d/light_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -85,6 +85,7 @@ protected: static void _bind_methods(); public: +#ifdef TOOLS_ENABLED virtual Dictionary _edit_get_state() const; virtual void _edit_set_state(const Dictionary &p_state); @@ -93,6 +94,7 @@ public: virtual bool _edit_use_pivot() const; virtual Rect2 _edit_get_rect() const; virtual bool _edit_use_rect() const; +#endif virtual Rect2 get_anchorable_rect() const; diff --git a/scene/2d/light_occluder_2d.cpp b/scene/2d/light_occluder_2d.cpp index 313b23b9d4..0e8e8f6679 100644 --- a/scene/2d/light_occluder_2d.cpp +++ b/scene/2d/light_occluder_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,6 +33,8 @@ #include "core/engine.h" #define LINE_GRAB_WIDTH 8 + +#ifdef TOOLS_ENABLED Rect2 OccluderPolygon2D::_edit_get_rect() const { if (rect_cache_dirty) { @@ -80,6 +82,7 @@ bool OccluderPolygon2D::_edit_is_selected_on_click(const Point2 &p_point, double return false; } } +#endif void OccluderPolygon2D::set_polygon(const PoolVector<Vector2> &p_polygon) { @@ -215,6 +218,7 @@ void LightOccluder2D::_notification(int p_what) { } } +#ifdef TOOLS_ENABLED Rect2 LightOccluder2D::_edit_get_rect() const { return occluder_polygon.is_valid() ? occluder_polygon->_edit_get_rect() : Rect2(); @@ -224,6 +228,7 @@ bool LightOccluder2D::_edit_is_selected_on_click(const Point2 &p_point, double p return occluder_polygon.is_valid() ? occluder_polygon->_edit_is_selected_on_click(p_point, p_tolerance) : false; } +#endif void LightOccluder2D::set_occluder_polygon(const Ref<OccluderPolygon2D> &p_polygon) { diff --git a/scene/2d/light_occluder_2d.h b/scene/2d/light_occluder_2d.h index 7931cd0b30..b20e347c35 100644 --- a/scene/2d/light_occluder_2d.h +++ b/scene/2d/light_occluder_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -57,8 +57,10 @@ protected: static void _bind_methods(); public: +#ifdef TOOLS_ENABLED virtual Rect2 _edit_get_rect() const; virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; +#endif void set_polygon(const PoolVector<Vector2> &p_polygon); PoolVector<Vector2> get_polygon() const; @@ -91,8 +93,10 @@ protected: static void _bind_methods(); public: +#ifdef TOOLS_ENABLED virtual Rect2 _edit_get_rect() const; virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; +#endif void set_occluder_polygon(const Ref<OccluderPolygon2D> &p_polygon); Ref<OccluderPolygon2D> get_occluder_polygon() const; diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp index ad405fabbb..c31840c8e1 100644 --- a/scene/2d/line_2d.cpp +++ b/scene/2d/line_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -47,8 +47,10 @@ Line2D::Line2D() { _texture_mode = LINE_TEXTURE_NONE; _sharp_limit = 2.f; _round_precision = 8; + _antialiased = false; } +#ifdef TOOLS_ENABLED Rect2 Line2D::_edit_get_rect() const { if (_points.size() == 0) @@ -78,6 +80,7 @@ bool Line2D::_edit_is_selected_on_click(const Point2 &p_point, double p_toleranc return false; } +#endif void Line2D::set_points(const PoolVector<Vector2> &p_points) { _points = p_points; @@ -260,6 +263,15 @@ int Line2D::get_round_precision() const { return _round_precision; } +void Line2D::set_antialiased(bool p_antialiased) { + _antialiased = p_antialiased; + update(); +} + +bool Line2D::get_antialiased() const { + return _antialiased; +} + void Line2D::_draw() { if (_points.size() <= 1 || _width == 0.f) return; @@ -305,8 +317,8 @@ void Line2D::_draw() { lb.vertices, lb.colors, lb.uvs, Vector<int>(), Vector<float>(), - - texture_rid); + texture_rid, -1, RID(), + _antialiased, true); // DEBUG // Draw wireframe @@ -386,6 +398,9 @@ void Line2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_round_precision", "precision"), &Line2D::set_round_precision); ClassDB::bind_method(D_METHOD("get_round_precision"), &Line2D::get_round_precision); + ClassDB::bind_method(D_METHOD("set_antialiased", "antialiased"), &Line2D::set_antialiased); + ClassDB::bind_method(D_METHOD("get_antialiased"), &Line2D::get_antialiased); + ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "points"), "set_points", "get_points"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "width"), "set_width", "get_width"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "width_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve", "get_curve"); @@ -401,6 +416,7 @@ void Line2D::_bind_methods() { ADD_GROUP("Border", ""); ADD_PROPERTY(PropertyInfo(Variant::REAL, "sharp_limit"), "set_sharp_limit", "get_sharp_limit"); ADD_PROPERTY(PropertyInfo(Variant::INT, "round_precision"), "set_round_precision", "get_round_precision"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "antialiased"), "set_antialiased", "get_antialiased"); BIND_ENUM_CONSTANT(LINE_JOINT_SHARP); BIND_ENUM_CONSTANT(LINE_JOINT_BEVEL); diff --git a/scene/2d/line_2d.h b/scene/2d/line_2d.h index 14afa463ba..3c7239f67c 100644 --- a/scene/2d/line_2d.h +++ b/scene/2d/line_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -56,11 +56,13 @@ public: LINE_TEXTURE_STRETCH }; - Line2D(); - +#ifdef TOOLS_ENABLED virtual Rect2 _edit_get_rect() const; virtual bool _edit_use_rect() const; virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; +#endif + + Line2D(); void set_points(const PoolVector<Vector2> &p_points); PoolVector<Vector2> get_points() const; @@ -108,6 +110,9 @@ public: void set_round_precision(int precision); int get_round_precision() const; + void set_antialiased(bool p_antialiased); + bool get_antialiased() const; + protected: void _notification(int p_what); void _draw(); @@ -131,6 +136,7 @@ private: LineTextureMode _texture_mode; float _sharp_limit; int _round_precision; + bool _antialiased; }; #endif // LINE2D_H diff --git a/scene/2d/line_builder.cpp b/scene/2d/line_builder.cpp index 6436b3878f..3385f2fbe0 100644 --- a/scene/2d/line_builder.cpp +++ b/scene/2d/line_builder.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/line_builder.h b/scene/2d/line_builder.h index 91b4518f9b..9e3dbbd6c1 100644 --- a/scene/2d/line_builder.h +++ b/scene/2d/line_builder.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/mesh_instance_2d.cpp b/scene/2d/mesh_instance_2d.cpp index bcd4bca940..93432ec40b 100644 --- a/scene/2d/mesh_instance_2d.cpp +++ b/scene/2d/mesh_instance_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -94,6 +94,7 @@ Ref<Texture> MeshInstance2D::get_texture() const { return texture; } +#ifdef TOOLS_ENABLED Rect2 MeshInstance2D::_edit_get_rect() const { if (mesh.is_valid()) { @@ -103,6 +104,7 @@ Rect2 MeshInstance2D::_edit_get_rect() const { return Node2D::_edit_get_rect(); } +#endif MeshInstance2D::MeshInstance2D() { } diff --git a/scene/2d/mesh_instance_2d.h b/scene/2d/mesh_instance_2d.h index af552415ca..51f75a3ead 100644 --- a/scene/2d/mesh_instance_2d.h +++ b/scene/2d/mesh_instance_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -46,6 +46,10 @@ protected: static void _bind_methods(); public: +#ifdef TOOLS_ENABLED + virtual Rect2 _edit_get_rect() const; +#endif + void set_mesh(const Ref<Mesh> &p_mesh); Ref<Mesh> get_mesh() const; @@ -55,8 +59,6 @@ public: void set_normal_map(const Ref<Texture> &p_texture); Ref<Texture> get_normal_map() const; - virtual Rect2 _edit_get_rect() const; - MeshInstance2D(); }; diff --git a/scene/2d/multimesh_instance_2d.cpp b/scene/2d/multimesh_instance_2d.cpp index ca75302163..028459e778 100644 --- a/scene/2d/multimesh_instance_2d.cpp +++ b/scene/2d/multimesh_instance_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -94,6 +94,7 @@ Ref<Texture> MultiMeshInstance2D::get_normal_map() const { return normal_map; } +#ifdef TOOLS_ENABLED Rect2 MultiMeshInstance2D::_edit_get_rect() const { if (multimesh.is_valid()) { @@ -103,6 +104,7 @@ Rect2 MultiMeshInstance2D::_edit_get_rect() const { return Node2D::_edit_get_rect(); } +#endif MultiMeshInstance2D::MultiMeshInstance2D() { } diff --git a/scene/2d/multimesh_instance_2d.h b/scene/2d/multimesh_instance_2d.h index 3795497183..c3f3e52920 100644 --- a/scene/2d/multimesh_instance_2d.h +++ b/scene/2d/multimesh_instance_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -47,6 +47,10 @@ protected: static void _bind_methods(); public: +#ifdef TOOLS_ENABLED + virtual Rect2 _edit_get_rect() const; +#endif + void set_multimesh(const Ref<MultiMesh> &p_multimesh); Ref<MultiMesh> get_multimesh() const; @@ -56,8 +60,6 @@ public: void set_normal_map(const Ref<Texture> &p_texture); Ref<Texture> get_normal_map() const; - virtual Rect2 _edit_get_rect() const; - MultiMeshInstance2D(); ~MultiMeshInstance2D(); }; diff --git a/scene/2d/navigation_2d.cpp b/scene/2d/navigation_2d.cpp index c7d2dabbae..de01d97ad9 100644 --- a/scene/2d/navigation_2d.cpp +++ b/scene/2d/navigation_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,710 +29,52 @@ /*************************************************************************/ #include "navigation_2d.h" +#include "servers/navigation_2d_server.h" -#define USE_ENTRY_POINT - -void Navigation2D::_navpoly_link(int p_id) { - - ERR_FAIL_COND(!navpoly_map.has(p_id)); - NavMesh &nm = navpoly_map[p_id]; - ERR_FAIL_COND(nm.linked); - - PoolVector<Vector2> vertices = nm.navpoly->get_vertices(); - int len = vertices.size(); - if (len == 0) - return; - - PoolVector<Vector2>::Read r = vertices.read(); - - for (int i = 0; i < nm.navpoly->get_polygon_count(); i++) { - - //build - - List<Polygon>::Element *P = nm.polygons.push_back(Polygon()); - Polygon &p = P->get(); - p.owner = &nm; - - Vector<int> poly = nm.navpoly->get_polygon(i); - int plen = poly.size(); - const int *indices = poly.ptr(); - bool valid = true; - p.edges.resize(plen); - - Vector2 center; - float sum = 0; - - for (int j = 0; j < plen; j++) { - - int idx = indices[j]; - if (idx < 0 || idx >= len) { - valid = false; - break; - } - - Polygon::Edge e; - Vector2 ep = nm.xform.xform(r[idx]); - center += ep; - e.point = _get_point(ep); - p.edges.write[j] = e; - - int idxn = indices[(j + 1) % plen]; - if (idxn < 0 || idxn >= len) { - valid = false; - break; - } - - Vector2 epn = nm.xform.xform(r[idxn]); - - sum += (epn.x - ep.x) * (epn.y + ep.y); - } - - p.clockwise = sum > 0; - - if (!valid) { - nm.polygons.pop_back(); - ERR_CONTINUE(!valid); - } - - p.center = center / plen; - - //connect - - for (int j = 0; j < plen; j++) { - - int next = (j + 1) % plen; - EdgeKey ek(p.edges[j].point, p.edges[next].point); - - Map<EdgeKey, Connection>::Element *C = connections.find(ek); - if (!C) { +void Navigation2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_rid"), &Navigation2D::get_rid); - Connection c; - c.A = &p; - c.A_edge = j; - c.B = NULL; - c.B_edge = -1; - connections[ek] = c; - } else { + ClassDB::bind_method(D_METHOD("get_simple_path", "start", "end", "optimize"), &Navigation2D::get_simple_path, DEFVAL(true)); - if (C->get().B != NULL) { - ConnectionPending pending; - pending.polygon = &p; - pending.edge = j; - p.edges.write[j].P = C->get().pending.push_back(pending); - continue; - } + ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &Navigation2D::set_cell_size); + ClassDB::bind_method(D_METHOD("get_cell_size"), &Navigation2D::get_cell_size); - C->get().B = &p; - C->get().B_edge = j; - C->get().A->edges.write[C->get().A_edge].C = &p; - C->get().A->edges.write[C->get().A_edge].C_edge = j; - p.edges.write[j].C = C->get().A; - p.edges.write[j].C_edge = C->get().A_edge; - //connection successful. - } - } - } + ClassDB::bind_method(D_METHOD("set_edge_connection_margin", "margin"), &Navigation2D::set_edge_connection_margin); + ClassDB::bind_method(D_METHOD("get_edge_connection_margin"), &Navigation2D::get_edge_connection_margin); - nm.linked = true; + ADD_PROPERTY(PropertyInfo(Variant::REAL, "cell_size"), "set_cell_size", "get_cell_size"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "edge_connection_margin"), "set_edge_connection_margin", "get_edge_connection_margin"); } -void Navigation2D::_navpoly_unlink(int p_id) { - - ERR_FAIL_COND(!navpoly_map.has(p_id)); - NavMesh &nm = navpoly_map[p_id]; - ERR_FAIL_COND(!nm.linked); - - for (List<Polygon>::Element *E = nm.polygons.front(); E; E = E->next()) { - - Polygon &p = E->get(); - - int ec = p.edges.size(); - Polygon::Edge *edges = p.edges.ptrw(); - - for (int i = 0; i < ec; i++) { - int next = (i + 1) % ec; - - EdgeKey ek(edges[i].point, edges[next].point); - Map<EdgeKey, Connection>::Element *C = connections.find(ek); - ERR_CONTINUE(!C); - - if (edges[i].P) { - C->get().pending.erase(edges[i].P); - edges[i].P = NULL; - - } else if (C->get().B) { - //disconnect +void Navigation2D::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_READY: { + Navigation2DServer::get_singleton()->map_set_active(map, true); + } break; + case NOTIFICATION_EXIT_TREE: { - C->get().B->edges.write[C->get().B_edge].C = NULL; - C->get().B->edges.write[C->get().B_edge].C_edge = -1; - C->get().A->edges.write[C->get().A_edge].C = NULL; - C->get().A->edges.write[C->get().A_edge].C_edge = -1; - - if (C->get().A == &E->get()) { - - C->get().A = C->get().B; - C->get().A_edge = C->get().B_edge; - } - C->get().B = NULL; - C->get().B_edge = -1; - - if (C->get().pending.size()) { - //reconnect if something is pending - ConnectionPending cp = C->get().pending.front()->get(); - C->get().pending.pop_front(); - - C->get().B = cp.polygon; - C->get().B_edge = cp.edge; - C->get().A->edges.write[C->get().A_edge].C = cp.polygon; - C->get().A->edges.write[C->get().A_edge].C_edge = cp.edge; - cp.polygon->edges.write[cp.edge].C = C->get().A; - cp.polygon->edges.write[cp.edge].C_edge = C->get().A_edge; - cp.polygon->edges.write[cp.edge].P = NULL; - } - - } else { - connections.erase(C); - //erase - } - } + Navigation2DServer::get_singleton()->map_set_active(map, false); + } break; } - - nm.polygons.clear(); - - nm.linked = false; -} - -int Navigation2D::navpoly_add(const Ref<NavigationPolygon> &p_mesh, const Transform2D &p_xform, Object *p_owner) { - - int id = last_id++; - NavMesh nm; - nm.linked = false; - nm.navpoly = p_mesh; - nm.xform = p_xform; - nm.owner = p_owner; - navpoly_map[id] = nm; - - _navpoly_link(id); - - return id; } -void Navigation2D::navpoly_set_transform(int p_id, const Transform2D &p_xform) { - - ERR_FAIL_COND(!navpoly_map.has(p_id)); - NavMesh &nm = navpoly_map[p_id]; - if (nm.xform == p_xform) - return; //bleh - _navpoly_unlink(p_id); - nm.xform = p_xform; - _navpoly_link(p_id); +void Navigation2D::set_cell_size(float p_cell_size) { + cell_size = p_cell_size; + Navigation2DServer::get_singleton()->map_set_cell_size(map, cell_size); } -void Navigation2D::navpoly_remove(int p_id) { - ERR_FAIL_COND(!navpoly_map.has(p_id)); - _navpoly_unlink(p_id); - navpoly_map.erase(p_id); +void Navigation2D::set_edge_connection_margin(float p_edge_connection_margin) { + edge_connection_margin = p_edge_connection_margin; + Navigation2DServer::get_singleton()->map_set_edge_connection_margin(map, edge_connection_margin); } Vector<Vector2> Navigation2D::get_simple_path(const Vector2 &p_start, const Vector2 &p_end, bool p_optimize) { - - Polygon *begin_poly = NULL; - Polygon *end_poly = NULL; - Vector2 begin_point; - Vector2 end_point; - float begin_d = 1e20; - float end_d = 1e20; - - //look for point inside triangle - - for (Map<int, NavMesh>::Element *E = navpoly_map.front(); E; E = E->next()) { - - if (!E->get().linked) - continue; - for (List<Polygon>::Element *F = E->get().polygons.front(); F; F = F->next()) { - - Polygon &p = F->get(); - if (begin_d || end_d) { - for (int i = 2; i < p.edges.size(); i++) { - - if (begin_d > 0) { - - if (Geometry::is_point_in_triangle(p_start, _get_vertex(p.edges[0].point), _get_vertex(p.edges[i - 1].point), _get_vertex(p.edges[i].point))) { - - begin_poly = &p; - begin_point = p_start; - begin_d = 0; - if (end_d == 0) - break; - } - } - - if (end_d > 0) { - - if (Geometry::is_point_in_triangle(p_end, _get_vertex(p.edges[0].point), _get_vertex(p.edges[i - 1].point), _get_vertex(p.edges[i].point))) { - - end_poly = &p; - end_point = p_end; - end_d = 0; - if (begin_d == 0) - break; - } - } - } - } - - p.prev_edge = -1; - } - } - - //start or end not inside triangle.. look for closest segment :| - if (begin_d || end_d) { - for (Map<int, NavMesh>::Element *E = navpoly_map.front(); E; E = E->next()) { - - if (!E->get().linked) - continue; - for (List<Polygon>::Element *F = E->get().polygons.front(); F; F = F->next()) { - - Polygon &p = F->get(); - int es = p.edges.size(); - for (int i = 0; i < es; i++) { - - Vector2 edge[2] = { - _get_vertex(p.edges[i].point), - _get_vertex(p.edges[(i + 1) % es].point) - }; - - if (begin_d > 0) { - Vector2 spoint = Geometry::get_closest_point_to_segment_2d(p_start, edge); - float d = spoint.distance_to(p_start); - if (d < begin_d) { - begin_poly = &p; - begin_point = spoint; - begin_d = d; - } - } - - if (end_d > 0) { - Vector2 spoint = Geometry::get_closest_point_to_segment_2d(p_end, edge); - float d = spoint.distance_to(p_end); - if (d < end_d) { - end_poly = &p; - end_point = spoint; - end_d = d; - } - } - } - } - } - } - - if (!begin_poly || !end_poly) { - - return Vector<Vector2>(); //no path - } - - if (begin_poly == end_poly) { - - Vector<Vector2> path; - path.resize(2); - path.write[0] = begin_point; - path.write[1] = end_point; - return path; - } - - bool found_route = false; - - List<Polygon *> open_list; - - begin_poly->entry = p_start; - - for (int i = 0; i < begin_poly->edges.size(); i++) { - - if (begin_poly->edges[i].C) { - - begin_poly->edges[i].C->prev_edge = begin_poly->edges[i].C_edge; -#ifdef USE_ENTRY_POINT - Vector2 edge[2] = { - _get_vertex(begin_poly->edges[i].point), - _get_vertex(begin_poly->edges[(i + 1) % begin_poly->edges.size()].point) - }; - - Vector2 entry = Geometry::get_closest_point_to_segment_2d(begin_poly->entry, edge); - begin_poly->edges[i].C->distance = begin_poly->entry.distance_to(entry); - begin_poly->edges[i].C->entry = entry; -#else - begin_poly->edges[i].C->distance = begin_poly->center.distance_to(begin_poly->edges[i].C->center); -#endif - open_list.push_back(begin_poly->edges[i].C); - - if (begin_poly->edges[i].C == end_poly) { - found_route = true; - } - } - } - - while (!found_route) { - - if (open_list.size() == 0) { - break; - } - //check open list - - List<Polygon *>::Element *least_cost_poly = NULL; - float least_cost = 1e30; - - //this could be faster (cache previous results) - for (List<Polygon *>::Element *E = open_list.front(); E; E = E->next()) { - - Polygon *p = E->get(); - - float cost = p->distance; - -#ifdef USE_ENTRY_POINT - int es = p->edges.size(); - - float shortest_distance = 1e30; - - for (int i = 0; i < es; i++) { - Polygon::Edge &e = p->edges.write[i]; - - if (!e.C) - continue; - - Vector2 edge[2] = { - _get_vertex(p->edges[i].point), - _get_vertex(p->edges[(i + 1) % es].point) - }; - - Vector2 edge_point = Geometry::get_closest_point_to_segment_2d(p->entry, edge); - float dist = p->entry.distance_to(edge_point); - if (dist < shortest_distance) - shortest_distance = dist; - } - - cost += shortest_distance; -#else - cost += p->center.distance_to(end_point); -#endif - if (cost < least_cost) { - least_cost_poly = E; - least_cost = cost; - } - } - - Polygon *p = least_cost_poly->get(); - //open the neighbours for search - int es = p->edges.size(); - - for (int i = 0; i < es; i++) { - - Polygon::Edge &e = p->edges.write[i]; - - if (!e.C) - continue; - -#ifdef USE_ENTRY_POINT - Vector2 edge[2] = { - _get_vertex(p->edges[i].point), - _get_vertex(p->edges[(i + 1) % es].point) - }; - - Vector2 edge_entry = Geometry::get_closest_point_to_segment_2d(p->entry, edge); - float distance = p->entry.distance_to(edge_entry) + p->distance; - -#else - - float distance = p->center.distance_to(e.C->center) + p->distance; - -#endif - - if (e.C->prev_edge != -1) { - //oh this was visited already, can we win the cost? - - if (e.C->distance > distance) { - - e.C->prev_edge = e.C_edge; - e.C->distance = distance; -#ifdef USE_ENTRY_POINT - e.C->entry = edge_entry; -#endif - } - } else { - //add to open neighbours - - e.C->prev_edge = e.C_edge; - e.C->distance = distance; -#ifdef USE_ENTRY_POINT - e.C->entry = edge_entry; -#endif - - open_list.push_back(e.C); - - if (e.C == end_poly) { - //oh my reached end! stop algorithm - found_route = true; - break; - } - } - } - - if (found_route) - break; - - open_list.erase(least_cost_poly); - } - - if (found_route) { - - Vector<Vector2> path; - - if (p_optimize) { - //string pulling - - Vector2 apex_point = end_point; - Vector2 portal_left = apex_point; - Vector2 portal_right = apex_point; - Polygon *left_poly = end_poly; - Polygon *right_poly = end_poly; - Polygon *p = end_poly; - - while (p) { - - Vector2 left; - Vector2 right; - -//#define CLOCK_TANGENT(m_a,m_b,m_c) ( ((m_a)-(m_c)).cross((m_a)-(m_b)) ) -#define CLOCK_TANGENT(m_a, m_b, m_c) ((((m_a).x - (m_c).x) * ((m_b).y - (m_c).y) - ((m_b).x - (m_c).x) * ((m_a).y - (m_c).y))) - - if (p == begin_poly) { - left = begin_point; - right = begin_point; - } else { - int prev = p->prev_edge; - int prev_n = (p->prev_edge + 1) % p->edges.size(); - left = _get_vertex(p->edges[prev].point); - right = _get_vertex(p->edges[prev_n].point); - - if (p->clockwise) { - SWAP(left, right); - } - /*if (CLOCK_TANGENT(apex_point,left,(left+right)*0.5) < 0){ - SWAP(left,right); - }*/ - } - - bool skip = false; - - /* - print_line("-----\nAPEX: "+(apex_point-end_point)); - print_line("LEFT:"); - print_line("\tPortal: "+(portal_left-end_point)); - print_line("\tPoint: "+(left-end_point)); - print_line("\tLeft Tangent: "+rtos(CLOCK_TANGENT(apex_point,portal_left,left))); - print_line("\tLeft Distance: "+rtos(portal_left.distance_squared_to(apex_point))); - print_line("\tLeft Test: "+rtos(CLOCK_TANGENT(apex_point,left,portal_right))); - print_line("RIGHT:"); - print_line("\tPortal: "+(portal_right-end_point)); - print_line("\tPoint: "+(right-end_point)); - print_line("\tRight Tangent: "+rtos(CLOCK_TANGENT(apex_point,portal_right,right))); - print_line("\tRight Distance: "+rtos(portal_right.distance_squared_to(apex_point))); - print_line("\tRight Test: "+rtos(CLOCK_TANGENT(apex_point,right,portal_left))); - */ - - if (CLOCK_TANGENT(apex_point, portal_left, left) >= 0) { - //process - if (portal_left.is_equal_approx(apex_point) || CLOCK_TANGENT(apex_point, left, portal_right) > 0) { - left_poly = p; - portal_left = left; - } else { - - apex_point = portal_right; - p = right_poly; - left_poly = p; - portal_left = apex_point; - portal_right = apex_point; - if (!path.size() || !path[path.size() - 1].is_equal_approx(apex_point)) - path.push_back(apex_point); - skip = true; - } - } - - if (!skip && CLOCK_TANGENT(apex_point, portal_right, right) <= 0) { - //process - if (portal_right.is_equal_approx(apex_point) || CLOCK_TANGENT(apex_point, right, portal_left) < 0) { - right_poly = p; - portal_right = right; - } else { - - apex_point = portal_left; - p = left_poly; - right_poly = p; - portal_right = apex_point; - portal_left = apex_point; - if (!path.size() || !path[path.size() - 1].is_equal_approx(apex_point)) - path.push_back(apex_point); - } - } - - if (p != begin_poly) - p = p->edges[p->prev_edge].C; - else - p = NULL; - } - - } else { - //midpoints - Polygon *p = end_poly; - - while (true) { - int prev = p->prev_edge; - int prev_n = (p->prev_edge + 1) % p->edges.size(); - Vector2 point = (_get_vertex(p->edges[prev].point) + _get_vertex(p->edges[prev_n].point)) * 0.5; - path.push_back(point); - p = p->edges[prev].C; - if (p == begin_poly) - break; - } - } - - if (!path.size() || !path[path.size() - 1].is_equal_approx(begin_point)) { - path.push_back(begin_point); // Add the begin point - } else { - path.write[path.size() - 1] = begin_point; // Replace first midpoint by the exact begin point - } - - path.invert(); - - if (path.size() <= 1 || !path[path.size() - 1].is_equal_approx(end_point)) { - path.push_back(end_point); // Add the end point - } else { - path.write[path.size() - 1] = end_point; // Replace last midpoint by the exact end point - } - - return path; - } - - return Vector<Vector2>(); -} - -Vector2 Navigation2D::get_closest_point(const Vector2 &p_point) { - - Vector2 closest_point = Vector2(); - float closest_point_d = 1e20; - - for (Map<int, NavMesh>::Element *E = navpoly_map.front(); E; E = E->next()) { - - if (!E->get().linked) - continue; - for (List<Polygon>::Element *F = E->get().polygons.front(); F; F = F->next()) { - - Polygon &p = F->get(); - for (int i = 2; i < p.edges.size(); i++) { - - if (Geometry::is_point_in_triangle(p_point, _get_vertex(p.edges[0].point), _get_vertex(p.edges[i - 1].point), _get_vertex(p.edges[i].point))) { - - return p_point; //inside triangle, nothing else to discuss - } - } - } - } - - for (Map<int, NavMesh>::Element *E = navpoly_map.front(); E; E = E->next()) { - - if (!E->get().linked) - continue; - for (List<Polygon>::Element *F = E->get().polygons.front(); F; F = F->next()) { - - Polygon &p = F->get(); - int es = p.edges.size(); - for (int i = 0; i < es; i++) { - - Vector2 edge[2] = { - _get_vertex(p.edges[i].point), - _get_vertex(p.edges[(i + 1) % es].point) - }; - - Vector2 spoint = Geometry::get_closest_point_to_segment_2d(p_point, edge); - float d = spoint.distance_squared_to(p_point); - if (d < closest_point_d) { - - closest_point = spoint; - closest_point_d = d; - } - } - } - } - - return closest_point; -} - -Object *Navigation2D::get_closest_point_owner(const Vector2 &p_point) { - - Object *owner = NULL; - Vector2 closest_point = Vector2(); - float closest_point_d = 1e20; - - for (Map<int, NavMesh>::Element *E = navpoly_map.front(); E; E = E->next()) { - - if (!E->get().linked) - continue; - for (List<Polygon>::Element *F = E->get().polygons.front(); F; F = F->next()) { - - Polygon &p = F->get(); - for (int i = 2; i < p.edges.size(); i++) { - - if (Geometry::is_point_in_triangle(p_point, _get_vertex(p.edges[0].point), _get_vertex(p.edges[i - 1].point), _get_vertex(p.edges[i].point))) { - - return E->get().owner; - } - } - } - } - - for (Map<int, NavMesh>::Element *E = navpoly_map.front(); E; E = E->next()) { - - if (!E->get().linked) - continue; - for (List<Polygon>::Element *F = E->get().polygons.front(); F; F = F->next()) { - - Polygon &p = F->get(); - int es = p.edges.size(); - for (int i = 0; i < es; i++) { - - Vector2 edge[2] = { - _get_vertex(p.edges[i].point), - _get_vertex(p.edges[(i + 1) % es].point) - }; - - Vector2 spoint = Geometry::get_closest_point_to_segment_2d(p_point, edge); - float d = spoint.distance_squared_to(p_point); - if (d < closest_point_d) { - - closest_point = spoint; - closest_point_d = d; - owner = E->get().owner; - } - } - } - } - - return owner; -} - -void Navigation2D::_bind_methods() { - - ClassDB::bind_method(D_METHOD("navpoly_add", "mesh", "xform", "owner"), &Navigation2D::navpoly_add, DEFVAL(Variant())); - ClassDB::bind_method(D_METHOD("navpoly_set_transform", "id", "xform"), &Navigation2D::navpoly_set_transform); - ClassDB::bind_method(D_METHOD("navpoly_remove", "id"), &Navigation2D::navpoly_remove); - - ClassDB::bind_method(D_METHOD("get_simple_path", "start", "end", "optimize"), &Navigation2D::get_simple_path, DEFVAL(true)); - ClassDB::bind_method(D_METHOD("get_closest_point", "to_point"), &Navigation2D::get_closest_point); - ClassDB::bind_method(D_METHOD("get_closest_point_owner", "to_point"), &Navigation2D::get_closest_point_owner); + return Navigation2DServer::get_singleton()->map_get_path(map, p_start, p_end, p_optimize); } Navigation2D::Navigation2D() { - ERR_FAIL_COND(sizeof(Point) != 8); - cell_size = 1; // one pixel - last_id = 1; + map = Navigation2DServer::get_singleton()->map_create(); + set_cell_size(10); // Ten pixels + set_edge_connection_margin(100); } diff --git a/scene/2d/navigation_2d.h b/scene/2d/navigation_2d.h index b4d659ff5c..08642a5489 100644 --- a/scene/2d/navigation_2d.h +++ b/scene/2d/navigation_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -38,135 +38,30 @@ class Navigation2D : public Node2D { GDCLASS(Navigation2D, Node2D); - union Point { + RID map; + real_t cell_size; + real_t edge_connection_margin; - struct { - int64_t x : 32; - int64_t y : 32; - }; - - uint64_t key; - bool operator<(const Point &p_key) const { return key < p_key.key; } - }; - - struct EdgeKey { - - Point a; - Point b; - - bool operator<(const EdgeKey &p_key) const { - return (a.key == p_key.a.key) ? (b.key < p_key.b.key) : (a.key < p_key.a.key); - }; - - EdgeKey(const Point &p_a = Point(), const Point &p_b = Point()) : - a(p_a), - b(p_b) { - if (a.key > b.key) { - SWAP(a, b); - } - } - }; - - struct NavMesh; - struct Polygon; - - struct ConnectionPending { - - Polygon *polygon; - int edge; - }; - - struct Polygon { - - struct Edge { - Point point; - Polygon *C; //connection - int C_edge; - List<ConnectionPending>::Element *P; - Edge() { - C = NULL; - C_edge = -1; - P = NULL; - } - }; - - Vector<Edge> edges; - - Vector2 center; - Vector2 entry; - - float distance; - int prev_edge; - - bool clockwise; - - NavMesh *owner; - }; - - struct Connection { - - Polygon *A; - int A_edge; - Polygon *B; - int B_edge; - - List<ConnectionPending> pending; - - Connection() { - A = NULL; - B = NULL; - A_edge = -1; - B_edge = -1; - } - }; - - Map<EdgeKey, Connection> connections; - - struct NavMesh { - - Object *owner; - Transform2D xform; - bool linked; - Ref<NavigationPolygon> navpoly; - List<Polygon> polygons; - }; - - _FORCE_INLINE_ Point _get_point(const Vector2 &p_pos) const { - - int x = int(Math::floor(p_pos.x / cell_size)); - int y = int(Math::floor(p_pos.y / cell_size)); +protected: + static void _bind_methods(); + void _notification(int p_what); - Point p; - p.key = 0; - p.x = x; - p.y = y; - return p; +public: + RID get_rid() const { + return map; } - _FORCE_INLINE_ Vector2 _get_vertex(const Point &p_point) const { - - return Vector2(p_point.x, p_point.y) * cell_size; + void set_cell_size(float p_cell_size); + float get_cell_size() const { + return cell_size; } - void _navpoly_link(int p_id); - void _navpoly_unlink(int p_id); - - float cell_size; - Map<int, NavMesh> navpoly_map; - int last_id; - -protected: - static void _bind_methods(); - -public: - //API should be as dynamic as possible - int navpoly_add(const Ref<NavigationPolygon> &p_mesh, const Transform2D &p_xform, Object *p_owner = NULL); - void navpoly_set_transform(int p_id, const Transform2D &p_xform); - void navpoly_remove(int p_id); + void set_edge_connection_margin(float p_edge_connection_margin); + float get_edge_connection_margin() const { + return edge_connection_margin; + } Vector<Vector2> get_simple_path(const Vector2 &p_start, const Vector2 &p_end, bool p_optimize = true); - Vector2 get_closest_point(const Vector2 &p_point); - Object *get_closest_point_owner(const Vector2 &p_point); Navigation2D(); }; diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp new file mode 100644 index 0000000000..fe4d3b322f --- /dev/null +++ b/scene/2d/navigation_agent_2d.cpp @@ -0,0 +1,341 @@ +/*************************************************************************/ +/* navigation_agent_2d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "navigation_agent_2d.h" + +#include "core/engine.h" +#include "scene/2d/navigation_2d.h" +#include "servers/navigation_2d_server.h" + +void NavigationAgent2D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_target_desired_distance", "desired_distance"), &NavigationAgent2D::set_target_desired_distance); + ClassDB::bind_method(D_METHOD("get_target_desired_distance"), &NavigationAgent2D::get_target_desired_distance); + + ClassDB::bind_method(D_METHOD("set_radius", "radius"), &NavigationAgent2D::set_radius); + ClassDB::bind_method(D_METHOD("get_radius"), &NavigationAgent2D::get_radius); + + ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationAgent2D::set_navigation_node); + ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationAgent2D::get_navigation_node); + + ClassDB::bind_method(D_METHOD("set_neighbor_dist", "neighbor_dist"), &NavigationAgent2D::set_neighbor_dist); + ClassDB::bind_method(D_METHOD("get_neighbor_dist"), &NavigationAgent2D::get_neighbor_dist); + + ClassDB::bind_method(D_METHOD("set_max_neighbors", "max_neighbors"), &NavigationAgent2D::set_max_neighbors); + ClassDB::bind_method(D_METHOD("get_max_neighbors"), &NavigationAgent2D::get_max_neighbors); + + ClassDB::bind_method(D_METHOD("set_time_horizon", "time_horizon"), &NavigationAgent2D::set_time_horizon); + ClassDB::bind_method(D_METHOD("get_time_horizon"), &NavigationAgent2D::get_time_horizon); + + ClassDB::bind_method(D_METHOD("set_max_speed", "max_speed"), &NavigationAgent2D::set_max_speed); + ClassDB::bind_method(D_METHOD("get_max_speed"), &NavigationAgent2D::get_max_speed); + + ClassDB::bind_method(D_METHOD("set_path_max_distance", "max_speed"), &NavigationAgent2D::set_path_max_distance); + ClassDB::bind_method(D_METHOD("get_path_max_distance"), &NavigationAgent2D::get_path_max_distance); + + ClassDB::bind_method(D_METHOD("set_target_location", "location"), &NavigationAgent2D::set_target_location); + ClassDB::bind_method(D_METHOD("get_target_location"), &NavigationAgent2D::get_target_location); + ClassDB::bind_method(D_METHOD("get_next_location"), &NavigationAgent2D::get_next_location); + ClassDB::bind_method(D_METHOD("distance_to_target"), &NavigationAgent2D::distance_to_target); + ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &NavigationAgent2D::set_velocity); + ClassDB::bind_method(D_METHOD("get_nav_path"), &NavigationAgent2D::get_nav_path); + ClassDB::bind_method(D_METHOD("get_nav_path_index"), &NavigationAgent2D::get_nav_path_index); + ClassDB::bind_method(D_METHOD("is_target_reached"), &NavigationAgent2D::is_target_reached); + ClassDB::bind_method(D_METHOD("is_target_reachable"), &NavigationAgent2D::is_target_reachable); + ClassDB::bind_method(D_METHOD("is_navigation_finished"), &NavigationAgent2D::is_navigation_finished); + ClassDB::bind_method(D_METHOD("get_final_location"), &NavigationAgent2D::get_final_location); + + ClassDB::bind_method(D_METHOD("_avoidance_done", "new_velocity"), &NavigationAgent2D::_avoidance_done); + + ADD_PROPERTY(PropertyInfo(Variant::REAL, "target_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01"), "set_target_desired_distance", "get_target_desired_distance"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0.1,500,0.01"), "set_radius", "get_radius"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "neighbor_dist", PROPERTY_HINT_RANGE, "0.1,100000,0.01"), "set_neighbor_dist", "get_neighbor_dist"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_neighbors", PROPERTY_HINT_RANGE, "1,10000,1"), "set_max_neighbors", "get_max_neighbors"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "time_horizon", PROPERTY_HINT_RANGE, "0.1,10000,0.01"), "set_time_horizon", "get_time_horizon"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_speed", PROPERTY_HINT_RANGE, "0.1,100000,0.01"), "set_max_speed", "get_max_speed"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "path_max_distance", PROPERTY_HINT_RANGE, "10,100,1"), "set_path_max_distance", "get_path_max_distance"); + + ADD_SIGNAL(MethodInfo("path_changed")); + ADD_SIGNAL(MethodInfo("target_reached")); + ADD_SIGNAL(MethodInfo("navigation_finished")); + ADD_SIGNAL(MethodInfo("velocity_computed", PropertyInfo(Variant::VECTOR3, "safe_velocity"))); +} + +void NavigationAgent2D::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_READY: { + + agent_parent = Object::cast_to<Node2D>(get_parent()); + + Navigation2DServer::get_singleton()->agent_set_callback(agent, this, "_avoidance_done"); + + // Search the navigation node and set it + { + Navigation2D *nav = NULL; + Node *p = get_parent(); + while (p != NULL) { + nav = Object::cast_to<Navigation2D>(p); + if (nav != NULL) + p = NULL; + else + p = p->get_parent(); + } + + set_navigation(nav); + } + + set_physics_process_internal(true); + } break; + case NOTIFICATION_EXIT_TREE: { + agent_parent = NULL; + set_navigation(NULL); + set_physics_process_internal(false); + } break; + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { + if (agent_parent) { + + Navigation2DServer::get_singleton()->agent_set_position(agent, agent_parent->get_global_transform().get_origin()); + if (!target_reached) { + if (distance_to_target() < target_desired_distance) { + emit_signal("target_reached"); + target_reached = true; + } + } + } + } break; + } +} + +NavigationAgent2D::NavigationAgent2D() : + agent_parent(NULL), + navigation(NULL), + agent(RID()), + target_desired_distance(1.0), + path_max_distance(3.0), + velocity_submitted(false), + target_reached(false), + navigation_finished(true) { + agent = Navigation2DServer::get_singleton()->agent_create(); + set_neighbor_dist(500.0); + set_max_neighbors(10); + set_time_horizon(20.0); + set_radius(10.0); + set_max_speed(200.0); +} + +NavigationAgent2D::~NavigationAgent2D() { + Navigation2DServer::get_singleton()->free(agent); + agent = RID(); // Pointless +} + +void NavigationAgent2D::set_navigation(Navigation2D *p_nav) { + if (navigation == p_nav) + return; // Pointless + + navigation = p_nav; + Navigation2DServer::get_singleton()->agent_set_map(agent, navigation == NULL ? RID() : navigation->get_rid()); +} + +void NavigationAgent2D::set_navigation_node(Node *p_nav) { + Navigation2D *nav = Object::cast_to<Navigation2D>(p_nav); + ERR_FAIL_COND(nav == NULL); + set_navigation(nav); +} + +Node *NavigationAgent2D::get_navigation_node() const { + return Object::cast_to<Node>(navigation); +} + +void NavigationAgent2D::set_target_desired_distance(real_t p_dd) { + target_desired_distance = p_dd; +} + +void NavigationAgent2D::set_radius(real_t p_radius) { + radius = p_radius; + Navigation2DServer::get_singleton()->agent_set_radius(agent, radius); +} + +void NavigationAgent2D::set_neighbor_dist(real_t p_dist) { + neighbor_dist = p_dist; + Navigation2DServer::get_singleton()->agent_set_neighbor_dist(agent, neighbor_dist); +} + +void NavigationAgent2D::set_max_neighbors(int p_count) { + max_neighbors = p_count; + Navigation2DServer::get_singleton()->agent_set_max_neighbors(agent, max_neighbors); +} + +void NavigationAgent2D::set_time_horizon(real_t p_time) { + time_horizon = p_time; + Navigation2DServer::get_singleton()->agent_set_time_horizon(agent, time_horizon); +} + +void NavigationAgent2D::set_max_speed(real_t p_max_speed) { + max_speed = p_max_speed; + Navigation2DServer::get_singleton()->agent_set_max_speed(agent, max_speed); +} + +void NavigationAgent2D::set_path_max_distance(real_t p_pmd) { + path_max_distance = p_pmd; +} + +real_t NavigationAgent2D::get_path_max_distance() { + return path_max_distance; +} + +void NavigationAgent2D::set_target_location(Vector2 p_location) { + target_location = p_location; + navigation_path.clear(); + target_reached = false; + navigation_finished = false; +} + +Vector2 NavigationAgent2D::get_target_location() const { + return target_location; +} + +Vector2 NavigationAgent2D::get_next_location() { + update_navigation(); + if (navigation_path.size() == 0) { + ERR_FAIL_COND_V(agent_parent == NULL, Vector2()); + return agent_parent->get_global_transform().get_origin(); + } else { + return navigation_path[nav_path_index]; + } +} + +real_t NavigationAgent2D::distance_to_target() const { + ERR_FAIL_COND_V(agent_parent == NULL, 0.0); + return agent_parent->get_global_transform().get_origin().distance_to(target_location); +} + +bool NavigationAgent2D::is_target_reached() const { + return target_reached; +} + +bool NavigationAgent2D::is_target_reachable() { + return target_desired_distance >= get_final_location().distance_to(target_location); +} + +bool NavigationAgent2D::is_navigation_finished() { + update_navigation(); + return navigation_finished; +} + +Vector2 NavigationAgent2D::get_final_location() { + update_navigation(); + if (navigation_path.size() == 0) { + return Vector2(); + } + return navigation_path[navigation_path.size() - 1]; +} + +void NavigationAgent2D::set_velocity(Vector2 p_velocity) { + target_velocity = p_velocity; + Navigation2DServer::get_singleton()->agent_set_target_velocity(agent, target_velocity); + Navigation2DServer::get_singleton()->agent_set_velocity(agent, prev_safe_velocity); + velocity_submitted = true; +} + +void NavigationAgent2D::_avoidance_done(Vector3 p_new_velocity) { + const Vector2 velocity = Vector2(p_new_velocity.x, p_new_velocity.z); + prev_safe_velocity = velocity; + + if (!velocity_submitted) { + target_velocity = Vector2(); + return; + } + velocity_submitted = false; + + emit_signal("velocity_computed", velocity); +} + +String NavigationAgent2D::get_configuration_warning() const { + if (!Object::cast_to<Node2D>(get_parent())) { + return TTR("The NavigationAgent2D can be used only under a Node2D node"); + } + + return String(); +} + +void NavigationAgent2D::update_navigation() { + + if (agent_parent == NULL) return; + if (navigation == NULL) return; + if (update_frame_id == Engine::get_singleton()->get_physics_frames()) return; + + update_frame_id = Engine::get_singleton()->get_physics_frames(); + + Vector2 o = agent_parent->get_global_transform().get_origin(); + + bool reload_path = false; + + if (Navigation2DServer::get_singleton()->agent_is_map_changed(agent)) { + reload_path = true; + } else if (navigation_path.size() == 0) { + reload_path = true; + } else { + // Check if too far from the navigation path + if (nav_path_index > 0) { + Vector2 segment[2]; + segment[0] = navigation_path[nav_path_index - 1]; + segment[1] = navigation_path[nav_path_index]; + Vector2 p = Geometry::get_closest_point_to_segment_2d(o, segment); + if (o.distance_to(p) >= path_max_distance) { + // To faraway, reload path + reload_path = true; + } + } + } + + if (reload_path) { + navigation_path = Navigation2DServer::get_singleton()->map_get_path(navigation->get_rid(), o, target_location, true); + navigation_finished = false; + nav_path_index = 0; + emit_signal("path_changed"); + } + + if (navigation_path.size() == 0) + return; + + // Check if we can advance the navigation path + if (navigation_finished == false) { + // Advances to the next far away location. + while (o.distance_to(navigation_path[nav_path_index]) < target_desired_distance) { + nav_path_index += 1; + if (nav_path_index == navigation_path.size()) { + nav_path_index -= 1; + navigation_finished = true; + emit_signal("navigation_finished"); + break; + } + } + } +} diff --git a/scene/2d/navigation_agent_2d.h b/scene/2d/navigation_agent_2d.h new file mode 100644 index 0000000000..60527091ce --- /dev/null +++ b/scene/2d/navigation_agent_2d.h @@ -0,0 +1,150 @@ +/*************************************************************************/ +/* navigation_agent_2d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef NAVIGATION_AGENT_2D_H +#define NAVIGATION_AGENT_2D_H + +#include "core/vector.h" +#include "scene/main/node.h" + +class Node2D; +class Navigation2D; + +class NavigationAgent2D : public Node { + GDCLASS(NavigationAgent2D, Node); + + Node2D *agent_parent; + Navigation2D *navigation; + + RID agent; + + real_t target_desired_distance; + real_t radius; + real_t neighbor_dist; + int max_neighbors; + real_t time_horizon; + real_t max_speed; + + real_t path_max_distance; + + Vector2 target_location; + Vector<Vector2> navigation_path; + int nav_path_index; + bool velocity_submitted; + Vector2 prev_safe_velocity; + /// The submitted target velocity + Vector2 target_velocity; + bool target_reached; + bool navigation_finished; + // No initialized on purpose + uint32_t update_frame_id; + +protected: + static void _bind_methods(); + void _notification(int p_what); + +public: + NavigationAgent2D(); + virtual ~NavigationAgent2D(); + + void set_navigation(Navigation2D *p_nav); + const Navigation2D *get_navigation() const { + return navigation; + } + + void set_navigation_node(Node *p_nav); + Node *get_navigation_node() const; + + RID get_rid() const { + return agent; + } + + void set_target_desired_distance(real_t p_dd); + real_t get_target_desired_distance() const { + return target_desired_distance; + } + + void set_radius(real_t p_radius); + real_t get_radius() const { + return radius; + } + + void set_neighbor_dist(real_t p_dist); + real_t get_neighbor_dist() const { + return neighbor_dist; + } + + void set_max_neighbors(int p_count); + int get_max_neighbors() const { + return max_neighbors; + } + + void set_time_horizon(real_t p_time); + real_t get_time_horizon() const { + return time_horizon; + } + + void set_max_speed(real_t p_max_speed); + real_t get_max_speed() const { + return max_speed; + } + + void set_path_max_distance(real_t p_pmd); + real_t get_path_max_distance(); + + void set_target_location(Vector2 p_location); + Vector2 get_target_location() const; + + Vector2 get_next_location(); + + Vector<Vector2> get_nav_path() const { + return navigation_path; + } + + int get_nav_path_index() const { + return nav_path_index; + } + + real_t distance_to_target() const; + bool is_target_reached() const; + bool is_target_reachable(); + bool is_navigation_finished(); + Vector2 get_final_location(); + + void set_velocity(Vector2 p_velocity); + void _avoidance_done(Vector3 p_new_velocity); + + virtual String get_configuration_warning() const; + +private: + void update_navigation(); +}; + +#endif diff --git a/scene/2d/navigation_obstacle_2d.cpp b/scene/2d/navigation_obstacle_2d.cpp new file mode 100644 index 0000000000..0740b616b6 --- /dev/null +++ b/scene/2d/navigation_obstacle_2d.cpp @@ -0,0 +1,154 @@ +/*************************************************************************/ +/* navigation_obstacle.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "navigation_obstacle_2d.h" + +#include "scene/2d/collision_shape_2d.h" +#include "scene/2d/navigation_2d.h" +#include "scene/2d/physics_body_2d.h" +#include "servers/navigation_2d_server.h" + +void NavigationObstacle2D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationObstacle2D::set_navigation_node); + ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationObstacle2D::get_navigation_node); +} + +void NavigationObstacle2D::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_READY: { + + update_agent_shape(); + + // Search the navigation node and set it + { + Navigation2D *nav = NULL; + Node *p = get_parent(); + while (p != NULL) { + nav = Object::cast_to<Navigation2D>(p); + if (nav != NULL) + p = NULL; + else + p = p->get_parent(); + } + + set_navigation(nav); + } + + set_physics_process_internal(true); + } break; + case NOTIFICATION_EXIT_TREE: { + set_navigation(NULL); + set_physics_process_internal(false); + } break; + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { + Node2D *node = Object::cast_to<Node2D>(get_parent()); + if (node) { + Navigation2DServer::get_singleton()->agent_set_position(agent, node->get_global_transform().get_origin()); + } + + } break; + } +} + +NavigationObstacle2D::NavigationObstacle2D() : + navigation(NULL), + agent(RID()) { + agent = Navigation2DServer::get_singleton()->agent_create(); +} + +NavigationObstacle2D::~NavigationObstacle2D() { + Navigation2DServer::get_singleton()->free(agent); + agent = RID(); // Pointless +} + +void NavigationObstacle2D::set_navigation(Navigation2D *p_nav) { + if (navigation == p_nav) + return; // Pointless + + navigation = p_nav; + Navigation2DServer::get_singleton()->agent_set_map(agent, navigation == NULL ? RID() : navigation->get_rid()); +} + +void NavigationObstacle2D::set_navigation_node(Node *p_nav) { + Navigation2D *nav = Object::cast_to<Navigation2D>(p_nav); + ERR_FAIL_COND(nav == NULL); + set_navigation(nav); +} + +Node *NavigationObstacle2D::get_navigation_node() const { + return Object::cast_to<Node>(navigation); +} + +String NavigationObstacle2D::get_configuration_warning() const { + if (!Object::cast_to<Node2D>(get_parent())) { + return TTR("The NavigationObstacle2D only serves to provide collision avoidance to a Node2D object."); + } + + return String(); +} + +void NavigationObstacle2D::update_agent_shape() { + Node *node = get_parent(); + + // Estimate the radius of this physics body + real_t radius = 0.0; + for (int i(0); i < node->get_child_count(); i++) { + // For each collision shape + CollisionShape2D *cs = Object::cast_to<CollisionShape2D>(node->get_child(i)); + if (cs) { + // Take the distance between the Body center to the shape center + real_t r = cs->get_transform().get_origin().length(); + if (cs->get_shape().is_valid()) { + // and add the enclosing shape radius + r += cs->get_shape()->get_enclosing_radius(); + } + Size2 s = cs->get_global_transform().get_scale(); + r *= MAX(s.x, s.y); + // Takes the biggest radius + radius = MAX(radius, r); + } + } + Node2D *node_2d = Object::cast_to<Node2D>(node); + if (node_2d) { + Vector2 s = node_2d->get_global_transform().get_scale(); + radius *= MAX(s.x, s.y); + } + + if (radius == 0.0) + radius = 1.0; // Never a 0 radius + + // Initialize the Agent as an object + Navigation2DServer::get_singleton()->agent_set_neighbor_dist(agent, 0.0); + Navigation2DServer::get_singleton()->agent_set_max_neighbors(agent, 0); + Navigation2DServer::get_singleton()->agent_set_time_horizon(agent, 0.0); + Navigation2DServer::get_singleton()->agent_set_radius(agent, radius); + Navigation2DServer::get_singleton()->agent_set_max_speed(agent, 0.0); +} diff --git a/scene/resources/video_stream.cpp b/scene/2d/navigation_obstacle_2d.h index a85db0c592..f098255799 100644 --- a/scene/resources/video_stream.cpp +++ b/scene/2d/navigation_obstacle_2d.h @@ -1,12 +1,12 @@ /*************************************************************************/ -/* video_stream.cpp */ +/* navigation_obstacle.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -28,12 +28,44 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "video_stream.h" +#ifndef NAVIGATION_OBSTACLE_2D_H +#define NAVIGATION_OBSTACLE_2D_H -void VideoStreamPlayback::_bind_methods(){ +#include "scene/main/node.h" -}; +class Navigation2D; + +class NavigationObstacle2D : public Node { + GDCLASS(NavigationObstacle2D, Node); + + Navigation2D *navigation; + + RID agent; + +protected: + static void _bind_methods(); + void _notification(int p_what); -VideoStreamPlayback::VideoStreamPlayback(){ +public: + NavigationObstacle2D(); + virtual ~NavigationObstacle2D(); + void set_navigation(Navigation2D *p_nav); + const Navigation2D *get_navigation() const { + return navigation; + } + + void set_navigation_node(Node *p_nav); + Node *get_navigation_node() const; + + RID get_rid() const { + return agent; + } + + virtual String get_configuration_warning() const; + +private: + void update_agent_shape(); }; + +#endif diff --git a/scene/2d/navigation_polygon.cpp b/scene/2d/navigation_polygon.cpp index 678db85ff0..c40cdb4720 100644 --- a/scene/2d/navigation_polygon.cpp +++ b/scene/2d/navigation_polygon.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,10 +32,13 @@ #include "core/core_string_names.h" #include "core/engine.h" +#include "core/os/mutex.h" #include "navigation_2d.h" +#include "servers/navigation_2d_server.h" #include "thirdparty/misc/triangulator.h" +#ifdef TOOLS_ENABLED Rect2 NavigationPolygon::_edit_get_rect() const { if (rect_cache_dirty) { @@ -75,9 +78,13 @@ bool NavigationPolygon::_edit_is_selected_on_click(const Point2 &p_point, double } return false; } +#endif void NavigationPolygon::set_vertices(const PoolVector<Vector2> &p_vertices) { + navmesh_generation->lock(); + navmesh.unref(); + navmesh_generation->unlock(); vertices = p_vertices; rect_cache_dirty = true; } @@ -89,6 +96,9 @@ PoolVector<Vector2> NavigationPolygon::get_vertices() const { void NavigationPolygon::_set_polygons(const Array &p_array) { + navmesh_generation->lock(); + navmesh.unref(); + navmesh_generation->unlock(); polygons.resize(p_array.size()); for (int i = 0; i < p_array.size(); i++) { polygons.write[i].indices = p_array[i]; @@ -131,6 +141,9 @@ void NavigationPolygon::add_polygon(const Vector<int> &p_polygon) { Polygon polygon; polygon.indices = p_polygon; polygons.push_back(polygon); + navmesh_generation->lock(); + navmesh.unref(); + navmesh_generation->unlock(); } void NavigationPolygon::add_outline_at_index(const PoolVector<Vector2> &p_outline, int p_index) { @@ -151,6 +164,34 @@ Vector<int> NavigationPolygon::get_polygon(int p_idx) { void NavigationPolygon::clear_polygons() { polygons.clear(); + navmesh_generation->lock(); + navmesh.unref(); + navmesh_generation->unlock(); +} + +Ref<NavigationMesh> NavigationPolygon::get_mesh() { + navmesh_generation->lock(); + if (navmesh.is_null()) { + navmesh.instance(); + PoolVector<Vector3> verts; + { + verts.resize(get_vertices().size()); + PoolVector<Vector3>::Write w = verts.write(); + + PoolVector<Vector2>::Read r = get_vertices().read(); + + for (int i(0); i < get_vertices().size(); i++) { + w[i] = Vector3(r[i].x, 0.0, r[i].y); + } + } + navmesh->set_vertices(verts); + + for (int i(0); i < get_polygon_count(); i++) { + navmesh->add_polygon(get_polygon(i)); + } + } + navmesh_generation->unlock(); + return navmesh; } void NavigationPolygon::add_outline(const PoolVector<Vector2> &p_outline) { @@ -189,6 +230,9 @@ void NavigationPolygon::clear_outlines() { } void NavigationPolygon::make_polygons_from_outlines() { + navmesh_generation->lock(); + navmesh.unref(); + navmesh_generation->unlock(); List<TriangulatorPoly> in_poly, out_poly; Vector2 outside_point(-1e10, -1e10); @@ -257,7 +301,7 @@ void NavigationPolygon::make_polygons_from_outlines() { TriangulatorPartition tpart; if (tpart.ConvexPartition_HM(&in_poly, &out_poly) == 0) { //failed! - ERR_PRINTS("NavigationPolygon: Convex partition failed!"); + ERR_PRINT("NavigationPolygon: Convex partition failed!"); return; } @@ -318,7 +362,9 @@ void NavigationPolygon::_bind_methods() { } NavigationPolygon::NavigationPolygon() : - rect_cache_dirty(true) { + rect_cache_dirty(true), + navmesh_generation(NULL) { + navmesh_generation = Mutex::create(); } void NavigationPolygonInstance::set_enabled(bool p_enabled) { @@ -332,18 +378,12 @@ void NavigationPolygonInstance::set_enabled(bool p_enabled) { if (!enabled) { - if (nav_id != -1) { - navigation->navpoly_remove(nav_id); - nav_id = -1; - } + Navigation2DServer::get_singleton()->region_set_map(region, RID()); } else { if (navigation) { - if (navpoly.is_valid()) { - - nav_id = navigation->navpoly_add(navpoly, get_relative_transform_to_parent(navigation), this); - } + Navigation2DServer::get_singleton()->region_set_map(region, navigation->get_rid()); } } @@ -357,7 +397,7 @@ bool NavigationPolygonInstance::is_enabled() const { } ///////////////////////////// - +#ifdef TOOLS_ENABLED Rect2 NavigationPolygonInstance::_edit_get_rect() const { return navpoly.is_valid() ? navpoly->_edit_get_rect() : Rect2(); @@ -367,6 +407,7 @@ bool NavigationPolygonInstance::_edit_is_selected_on_click(const Point2 &p_point return navpoly.is_valid() ? navpoly->_edit_is_selected_on_click(p_point, p_tolerance) : false; } +#endif void NavigationPolygonInstance::_notification(int p_what) { @@ -379,9 +420,9 @@ void NavigationPolygonInstance::_notification(int p_what) { navigation = Object::cast_to<Navigation2D>(c); if (navigation) { - if (enabled && navpoly.is_valid()) { + if (enabled) { - nav_id = navigation->navpoly_add(navpoly, get_relative_transform_to_parent(navigation), this); + Navigation2DServer::get_singleton()->region_set_map(region, navigation->get_rid()); } break; } @@ -392,19 +433,14 @@ void NavigationPolygonInstance::_notification(int p_what) { } break; case NOTIFICATION_TRANSFORM_CHANGED: { - if (navigation && nav_id != -1) { - navigation->navpoly_set_transform(nav_id, get_relative_transform_to_parent(navigation)); - } + Navigation2DServer::get_singleton()->region_set_transform(region, get_global_transform()); } break; case NOTIFICATION_EXIT_TREE: { if (navigation) { - if (nav_id != -1) { - navigation->navpoly_remove(nav_id); - nav_id = -1; - } + Navigation2DServer::get_singleton()->region_set_map(region, RID()); } navigation = NULL; } break; @@ -463,24 +499,18 @@ void NavigationPolygonInstance::set_navigation_polygon(const Ref<NavigationPolyg return; } - if (navigation && nav_id != -1) { - navigation->navpoly_remove(nav_id); - nav_id = -1; - } - if (navpoly.is_valid()) { navpoly->disconnect(CoreStringNames::get_singleton()->changed, this, "_navpoly_changed"); } + navpoly = p_navpoly; + Navigation2DServer::get_singleton()->region_set_navpoly(region, p_navpoly); + if (navpoly.is_valid()) { navpoly->connect(CoreStringNames::get_singleton()->changed, this, "_navpoly_changed"); } _navpoly_changed(); - if (navigation && navpoly.is_valid() && enabled) { - nav_id = navigation->navpoly_add(navpoly, get_relative_transform_to_parent(navigation), this); - } - _change_notify("navpoly"); update_configuration_warning(); } @@ -533,8 +563,13 @@ void NavigationPolygonInstance::_bind_methods() { NavigationPolygonInstance::NavigationPolygonInstance() { - navigation = NULL; - nav_id = -1; enabled = true; set_notify_transform(true); + region = Navigation2DServer::get_singleton()->region_create(); + + navigation = NULL; +} + +NavigationPolygonInstance::~NavigationPolygonInstance() { + Navigation2DServer::get_singleton()->free(region); } diff --git a/scene/2d/navigation_polygon.h b/scene/2d/navigation_polygon.h index ebbe67d949..92cfc8f5e6 100644 --- a/scene/2d/navigation_polygon.h +++ b/scene/2d/navigation_polygon.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,6 +32,9 @@ #define NAVIGATION_POLYGON_H #include "scene/2d/node_2d.h" +#include "scene/resources/navigation_mesh.h" + +class Mutex; class NavigationPolygon : public Resource { @@ -47,6 +50,10 @@ class NavigationPolygon : public Resource { mutable Rect2 item_rect; mutable bool rect_cache_dirty; + Mutex *navmesh_generation; + // Navigation mesh + Ref<NavigationMesh> navmesh; + protected: static void _bind_methods(); @@ -57,8 +64,10 @@ protected: Array _get_outlines() const; public: +#ifdef TOOLS_ENABLED Rect2 _edit_get_rect() const; bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; +#endif void set_vertices(const PoolVector<Vector2> &p_vertices); PoolVector<Vector2> get_vertices() const; @@ -79,6 +88,8 @@ public: Vector<int> get_polygon(int p_idx); void clear_polygons(); + Ref<NavigationMesh> get_mesh(); + NavigationPolygon(); }; @@ -89,7 +100,7 @@ class NavigationPolygonInstance : public Node2D { GDCLASS(NavigationPolygonInstance, Node2D); bool enabled; - int nav_id; + RID region; Navigation2D *navigation; Ref<NavigationPolygon> navpoly; @@ -100,8 +111,10 @@ protected: static void _bind_methods(); public: +#ifdef TOOLS_ENABLED virtual Rect2 _edit_get_rect() const; virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; +#endif void set_enabled(bool p_enabled); bool is_enabled() const; @@ -112,6 +125,7 @@ public: String get_configuration_warning() const; NavigationPolygonInstance(); + ~NavigationPolygonInstance(); }; #endif // NAVIGATIONPOLYGON_H diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index 336c8aa78e..7deebe9b27 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -35,6 +35,7 @@ #include "scene/main/viewport.h" #include "servers/visual_server.h" +#ifdef TOOLS_ENABLED Dictionary Node2D::_edit_get_state() const { Dictionary state; @@ -44,6 +45,7 @@ Dictionary Node2D::_edit_get_state() const { return state; } + void Node2D::_edit_set_state(const Dictionary &p_state) { pos = p_state["position"]; @@ -119,6 +121,7 @@ void Node2D::_edit_set_rect(const Rect2 &p_edit_rect) { _change_notify("scale"); _change_notify("position"); } +#endif void Node2D::_update_xform_values() { @@ -170,6 +173,7 @@ void Node2D::set_scale(const Size2 &p_scale) { if (_xform_dirty) ((Node2D *)this)->_update_xform_values(); _scale = p_scale; + // Avoid having 0 scale values, can lead to errors in physics and rendering. if (_scale.x == 0) _scale.x = CMP_EPSILON; if (_scale.y == 0) diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h index c07dc88720..00202481a6 100644 --- a/scene/2d/node_2d.h +++ b/scene/2d/node_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -55,6 +55,7 @@ protected: static void _bind_methods(); public: +#ifdef TOOLS_ENABLED virtual Dictionary _edit_get_state() const; virtual void _edit_set_state(const Dictionary &p_state); @@ -69,6 +70,7 @@ public: virtual bool _edit_use_rotation() const; virtual void _edit_set_rect(const Rect2 &p_edit_rect); +#endif void set_position(const Point2 &p_pos); void set_rotation(float p_radians); diff --git a/scene/2d/parallax_background.cpp b/scene/2d/parallax_background.cpp index 4ead1bbd1e..0d5f74a265 100644 --- a/scene/2d/parallax_background.cpp +++ b/scene/2d/parallax_background.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/parallax_background.h b/scene/2d/parallax_background.h index 38d59ac737..25ccd910d1 100644 --- a/scene/2d/parallax_background.h +++ b/scene/2d/parallax_background.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/parallax_layer.cpp b/scene/2d/parallax_layer.cpp index 0823e09110..5aea1025ef 100644 --- a/scene/2d/parallax_layer.cpp +++ b/scene/2d/parallax_layer.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/parallax_layer.h b/scene/2d/parallax_layer.h index b5db111a38..ba59184649 100644 --- a/scene/2d/parallax_layer.h +++ b/scene/2d/parallax_layer.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp index 0bf8237d37..746feeaa82 100644 --- a/scene/2d/particles_2d.cpp +++ b/scene/2d/particles_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/particles_2d.h b/scene/2d/particles_2d.h index 0276978f83..56c328fc38 100644 --- a/scene/2d/particles_2d.h +++ b/scene/2d/particles_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp index 55c8c7f229..ef7c343c1a 100644 --- a/scene/2d/path_2d.cpp +++ b/scene/2d/path_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -37,6 +37,7 @@ #include "editor/editor_scale.h" #endif +#ifdef TOOLS_ENABLED Rect2 Path2D::_edit_get_rect() const { if (!curve.is_valid() || curve->get_point_count() == 0) @@ -85,6 +86,7 @@ bool Path2D::_edit_is_selected_on_click(const Point2 &p_point, double p_toleranc return false; } +#endif void Path2D::_notification(int p_what) { @@ -118,9 +120,15 @@ void Path2D::_notification(int p_what) { } void Path2D::_curve_changed() { + if (!is_inside_tree()) { + return; + } - if (is_inside_tree() && Engine::get_singleton()->is_editor_hint()) - update(); + if (!Engine::get_singleton()->is_editor_hint() && !get_tree()->is_debugging_navigation_hint()) { + return; + } + + update(); } void Path2D::set_curve(const Ref<Curve2D> &p_curve) { @@ -173,16 +181,10 @@ void PathFollow2D::_update_transform() { if (path_length == 0) { return; } - float bounded_offset = offset; - if (loop) - bounded_offset = Math::fposmod(bounded_offset, path_length); - else - bounded_offset = CLAMP(bounded_offset, 0, path_length); - - Vector2 pos = c->interpolate_baked(bounded_offset, cubic); + Vector2 pos = c->interpolate_baked(offset, cubic); if (rotate) { - float ahead = bounded_offset + lookahead; + float ahead = offset + lookahead; if (loop && ahead >= path_length) { // If our lookahead will loop, we need to check if the path is closed. @@ -206,7 +208,7 @@ void PathFollow2D::_update_transform() { // This will happen at the end of non-looping or non-closed paths. // We'll try a look behind instead, in order to get a meaningful angle. tangent_to_curve = - (pos - c->interpolate_baked(bounded_offset - lookahead, cubic)).normalized(); + (pos - c->interpolate_baked(offset - lookahead, cubic)).normalized(); } else { tangent_to_curve = (ahead_pos - pos).normalized(); } @@ -264,7 +266,7 @@ void PathFollow2D::_validate_property(PropertyInfo &property) const { if (path && path->get_curve().is_valid()) max = path->get_curve()->get_baked_length(); - property.hint_string = "0," + rtos(max) + ",0.01,or_lesser"; + property.hint_string = "0," + rtos(max) + ",0.01,or_lesser,or_greater"; } } @@ -306,8 +308,8 @@ void PathFollow2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_lookahead", "lookahead"), &PathFollow2D::set_lookahead); ClassDB::bind_method(D_METHOD("get_lookahead"), &PathFollow2D::get_lookahead); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "offset", PROPERTY_HINT_RANGE, "0,10000,0.01,or_lesser"), "set_offset", "get_offset"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_offset", PROPERTY_HINT_RANGE, "0,1,0.0001,or_lesser", PROPERTY_USAGE_EDITOR), "set_unit_offset", "get_unit_offset"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "offset", PROPERTY_HINT_RANGE, "0,10000,0.01,or_lesser,or_greater"), "set_offset", "get_offset"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_offset", PROPERTY_HINT_RANGE, "0,1,0.0001,or_lesser,or_greater", PROPERTY_USAGE_EDITOR), "set_unit_offset", "get_unit_offset"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "h_offset"), "set_h_offset", "get_h_offset"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "v_offset"), "set_v_offset", "get_v_offset"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rotate"), "set_rotate", "is_rotating"); diff --git a/scene/2d/path_2d.h b/scene/2d/path_2d.h index 4efad19938..35cf8211f4 100644 --- a/scene/2d/path_2d.h +++ b/scene/2d/path_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -47,9 +47,11 @@ protected: static void _bind_methods(); public: +#ifdef TOOLS_ENABLED virtual Rect2 _edit_get_rect() const; virtual bool _edit_use_rect() const; virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; +#endif void set_curve(const Ref<Curve2D> &p_curve); Ref<Curve2D> get_curve() const; diff --git a/scene/2d/path_texture.cpp b/scene/2d/path_texture.cpp index 3de2079ebe..df59c9e2bb 100644 --- a/scene/2d/path_texture.cpp +++ b/scene/2d/path_texture.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/path_texture.h b/scene/2d/path_texture.h index 313aa772c4..9cfa004cfb 100644 --- a/scene/2d/path_texture.h +++ b/scene/2d/path_texture.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 3a4f397fe0..d42bd6adaf 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -1051,7 +1051,7 @@ void RigidBody2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "gravity_scale", PROPERTY_HINT_RANGE, "-128,128,0.01"), "set_gravity_scale", "get_gravity_scale"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator"); ADD_PROPERTY(PropertyInfo(Variant::INT, "continuous_cd", PROPERTY_HINT_ENUM, "Disabled,Cast Ray,Cast Shape"), "set_continuous_collision_detection_mode", "get_continuous_collision_detection_mode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "contacts_reported"), "set_max_contacts_reported", "get_max_contacts_reported"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "contacts_reported", PROPERTY_HINT_RANGE, "0,64,1,or_greater"), "set_max_contacts_reported", "get_max_contacts_reported"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "contact_monitor"), "set_contact_monitor", "is_contact_monitor_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleeping", "is_sleeping"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_sleep"), "set_can_sleep", "is_able_to_sleep"); @@ -1212,36 +1212,37 @@ bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_ //so, if you pass 45 as limit, avoid numerical precision errors when angle is 45. #define FLOOR_ANGLE_THRESHOLD 0.01 -Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { +Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { - Vector2 floor_motion = floor_velocity; + Vector2 body_velocity = p_linear_velocity; + Vector2 body_velocity_normal = body_velocity.normalized(); + + Vector2 current_floor_velocity = floor_velocity; if (on_floor && on_floor_body.is_valid()) { //this approach makes sure there is less delay between the actual body velocity and the one we saved Physics2DDirectBodyState *bs = Physics2DServer::get_singleton()->body_get_direct_state(on_floor_body); if (bs) { - floor_motion = bs->get_linear_velocity(); + current_floor_velocity = bs->get_linear_velocity(); } } // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky - Vector2 motion = (floor_motion + p_linear_velocity) * (Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time()); - Vector2 lv = p_linear_velocity; + Vector2 motion = (current_floor_velocity + body_velocity) * (Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time()); on_floor = false; on_floor_body = RID(); on_ceiling = false; on_wall = false; colliders.clear(); + floor_normal = Vector2(); floor_velocity = Vector2(); - Vector2 lv_n = p_linear_velocity.normalized(); - while (p_max_slides) { Collision collision; bool found_collision = false; - for (int i = 0; i < 2; i++) { + for (int i = 0; i < 2; ++i) { bool collided; if (i == 0) { //collide collided = move_and_collide(motion, p_infinite_inertia, collision); @@ -1262,54 +1263,51 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const colliders.push_back(collision); motion = collision.remainder; - if (p_floor_direction == Vector2()) { + if (p_up_direction == Vector2()) { //all is a wall on_wall = true; } else { - if (Math::acos(collision.normal.dot(p_floor_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor + if (Math::acos(collision.normal.dot(p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor on_floor = true; + floor_normal = collision.normal; on_floor_body = collision.collider_rid; floor_velocity = collision.collider_vel; if (p_stop_on_slope) { - if ((lv_n + p_floor_direction).length() < 0.01 && collision.travel.length() < 1) { + if ((body_velocity_normal + p_up_direction).length() < 0.01 && collision.travel.length() < 1) { Transform2D gt = get_global_transform(); - gt.elements[2] -= collision.travel.project(p_floor_direction.tangent()); + gt.elements[2] -= collision.travel.slide(p_up_direction); set_global_transform(gt); return Vector2(); } } - - } else if (Math::acos(collision.normal.dot(-p_floor_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling + } else if (Math::acos(collision.normal.dot(-p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling on_ceiling = true; } else { on_wall = true; } } - Vector2 n = collision.normal; - motion = motion.slide(n); - lv = lv.slide(n); + motion = motion.slide(collision.normal); + body_velocity = body_velocity.slide(collision.normal); } } - if (!found_collision) { - break; - } - p_max_slides--; - if (motion == Vector2()) + if (!found_collision || motion == Vector2()) break; + + --p_max_slides; } - return lv; + return body_velocity; } -Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_floor_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { +Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { bool was_on_floor = on_floor; - Vector2 ret = move_and_slide(p_linear_velocity, p_floor_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia); + Vector2 ret = move_and_slide(p_linear_velocity, p_up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia); if (!was_on_floor || p_snap == Vector2()) { return ret; } @@ -1319,15 +1317,16 @@ Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_veloci if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) { bool apply = true; - if (p_floor_direction != Vector2()) { - if (Math::acos(p_floor_direction.normalized().dot(col.normal)) < p_floor_max_angle) { + if (p_up_direction != Vector2()) { + if (Math::acos(p_up_direction.normalized().dot(col.normal)) < p_floor_max_angle) { on_floor = true; + floor_normal = col.normal; on_floor_body = col.collider_rid; floor_velocity = col.collider_vel; if (p_stop_on_slope) { // move and collide may stray the object a bit because of pre un-stucking, // so only ensure that motion happens on floor direction in this case. - col.travel = p_floor_direction * p_floor_direction.dot(col.travel); + col.travel = p_up_direction * p_up_direction.dot(col.travel); } } else { @@ -1357,6 +1356,11 @@ bool KinematicBody2D::is_on_ceiling() const { return on_ceiling; } +Vector2 KinematicBody2D::get_floor_normal() const { + + return floor_normal; +} + Vector2 KinematicBody2D::get_floor_velocity() const { return floor_velocity; @@ -1469,14 +1473,15 @@ void KinematicBody2D::_notification(int p_what) { void KinematicBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "exclude_raycast_shapes", "test_only"), &KinematicBody2D::_move, DEFVAL(true), DEFVAL(true), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody2D::move_and_slide, DEFVAL(Vector2(0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true)); - ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "floor_normal", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody2D::move_and_slide_with_snap, DEFVAL(Vector2(0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody2D::move_and_slide, DEFVAL(Vector2(0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody2D::move_and_slide_with_snap, DEFVAL(Vector2(0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true)); ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia"), &KinematicBody2D::test_move, DEFVAL(true)); ClassDB::bind_method(D_METHOD("is_on_floor"), &KinematicBody2D::is_on_floor); ClassDB::bind_method(D_METHOD("is_on_ceiling"), &KinematicBody2D::is_on_ceiling); ClassDB::bind_method(D_METHOD("is_on_wall"), &KinematicBody2D::is_on_wall); + ClassDB::bind_method(D_METHOD("get_floor_normal"), &KinematicBody2D::get_floor_normal); ClassDB::bind_method(D_METHOD("get_floor_velocity"), &KinematicBody2D::get_floor_velocity); ClassDB::bind_method(D_METHOD("set_safe_margin", "pixels"), &KinematicBody2D::set_safe_margin); diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index 66e5ce250f..6766bafde3 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -306,6 +306,7 @@ public: private: float margin; + Vector2 floor_normal; Vector2 floor_velocity; RID on_floor_body; bool on_floor; @@ -339,11 +340,12 @@ public: void set_safe_margin(float p_margin); float get_safe_margin() const; - Vector2 move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction = Vector2(0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); - Vector2 move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_floor_direction = Vector2(0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); + Vector2 move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_up_direction = Vector2(0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); + Vector2 move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_up_direction = Vector2(0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); bool is_on_floor() const; bool is_on_wall() const; bool is_on_ceiling() const; + Vector2 get_floor_normal() const; Vector2 get_floor_velocity() const; int get_slide_count() const; diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp index 5e14959e9d..a6da027e0a 100644 --- a/scene/2d/polygon_2d.cpp +++ b/scene/2d/polygon_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,6 +33,7 @@ #include "core/math/geometry.h" #include "skeleton_2d.h" +#ifdef TOOLS_ENABLED Dictionary Polygon2D::_edit_get_state() const { Dictionary state = Node2D::_edit_get_state(); state["offset"] = offset; @@ -87,6 +88,7 @@ bool Polygon2D::_edit_is_selected_on_click(const Point2 &p_point, double p_toler } return Geometry::is_point_in_polygon(p_point - get_offset(), polygon2d); } +#endif void Polygon2D::_skeleton_bone_setup_changed() { update(); @@ -308,7 +310,7 @@ void Polygon2D::_notification(int p_what) { if (invert || polygons.size() == 0) { Vector<int> indices = Geometry::triangulate_polygon(points); if (indices.size()) { - VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID()); + VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID(), -1, RID(), antialiased); } } else { //draw individual polygons @@ -342,197 +344,8 @@ void Polygon2D::_notification(int p_what) { } if (total_indices.size()) { - VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), total_indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID()); - } - -#if 0 - //use splits - Vector<int> loop; - int sc = splits.size(); - PoolVector<int>::Read r = splits.read(); - - - print_line("has splits, amount " + itos(splits.size())); - Vector<Vector<int> > loops; - - // find a point that can be used to begin, must not be in a split, and have to the left and right the same one - // like this one -> x---o - // \ / \ . - // o---o - int base_point = -1; - { - int current_point = -1; - int base_point_prev_split = -1; - - - for (int i = 0; i < points.size(); i++) { - - //find if this point is in a split - int split_index = -1; - bool has_prev_split = false; - int min_dist_to_end = 0x7FFFFFFF; - - for (int j = 0; j < sc; j += 2) { - - int split_pos = -1; - int split_end = -1; - - if (r[j + 0] == i) { //found split in first point - split_pos = r[j + 0]; - split_end = r[j + 1]; - } else if (r[j + 1] == i) { //found split in second point - split_pos = r[j + 1]; - split_end = r[j + 0]; - } - - if (split_pos == split_end) { - continue; //either nothing found or begin == end, this not a split in either case - } - - if (j == base_point_prev_split) { - has_prev_split = true; - } - - //compute distance from split pos to split end in current traversal direction - int dist_to_end = split_end > split_pos ? split_end - split_pos : (last - split_pos + split_end); - - if (dist_to_end < min_dist_to_end) { - //always keep the valid split with the least distance to the loop - min_dist_to_end = dist_to_end; - split_index = j; - } - } - - if (split_index == -1) { - current_point = i; //no split here, we are testing this point - } else if (has_prev_split) { - base_point = current_point; // there is a split and it contains the previous visited split, success - break; - } else { - //invalidate current point and keep split - current_point = -1; - base_point_prev_split = split_index; - } - } - } - - print_line("found base point: " + itos(base_point)); - - if (base_point != -1) { - - int point = base_point; - int last = base_point; - //go through all the points, find splits - do { - - int split; - int last_dist_to_end = -1; //maximum valid distance to end - - do { - - loop.push_back(point); //push current point - - split = -1; - int end = -1; - - int max_dist_to_end = 0; - - //find if this point is in a split - for (int j = 0; j < sc; j += 2) { - - int split_pos = -1; - int split_end = -1; - - if (r[j + 0] == point) { //match first split index - split_pos = r[j + 0]; - split_end = r[j + 1]; - } else if (r[j + 1] == point) { //match second split index - split_pos = r[j + 1]; - split_end = r[j + 0]; - } - - if (split_pos == split_end) { - continue; //either nothing found or begin == end, this not a split in either case - } - - //compute distance from split pos to split end - int dist_to_end = split_end > split_pos ? split_end - split_pos : (points.size() - split_pos + split_end); - - if (last_dist_to_end != -1 && dist_to_end >= last_dist_to_end) { - //distance must be shorter than in last iteration, means we've tested this before so ignore - continue; - } else if (dist_to_end > max_dist_to_end) { - //always keep the valid point with the most distance (as long as it's valid) - max_dist_to_end = dist_to_end; - split = split_pos; - end = split_end; - } - } - - if (split != -1) { - //found a split! - int from = end; - - //add points until last is reached - while (true) { - //find if point is in a split - loop.push_back(from); - - if (from == last) { - break; - } - - from++; - if (from >= points.size()) { //wrap if reached end - from = 0; - } - - if (from == loop[0]) { - break; //end because we reached split source - } - } - - loops.push_back(loop); //done with this loop - loop.clear(); - - last_dist_to_end = max_dist_to_end; - last = end; //algorithm can safely finish in this split point - } - - } while (split != -1); - - } while (point != last); - } - - if (loop.size() >=2 ) { //points remained - //points remain - loop.push_back(last); //no splits found, use last - loops.push_back(loop); - } - - print_line("total loops: " + itos(loops.size())); - - if (loops.size()) { //loops found - Vector<int> indices; - - for (int i = 0; i < loops.size(); i++) { - Vector<int> loop = loops[i]; - Vector<Vector2> vertices; - vertices.resize(loop.size()); - for (int j = 0; j < vertices.size(); j++) { - vertices.write[j] = points[loop[j]]; - } - Vector<int> sub_indices = Geometry::triangulate_polygon(vertices); - int from = indices.size(); - indices.resize(from + sub_indices.size()); - for (int j = 0; j < sub_indices.size(); j++) { - indices.write[from + j] = loop[sub_indices[j]]; - } - } - - VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID()); + VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), total_indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID(), -1, RID(), antialiased); } -#endif } } break; diff --git a/scene/2d/polygon_2d.h b/scene/2d/polygon_2d.h index f25b3885b0..07b8828532 100644 --- a/scene/2d/polygon_2d.h +++ b/scene/2d/polygon_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -77,6 +77,7 @@ protected: static void _bind_methods(); public: +#ifdef TOOLS_ENABLED virtual Dictionary _edit_get_state() const; virtual void _edit_set_state(const Dictionary &p_state); @@ -87,6 +88,7 @@ public: virtual bool _edit_use_rect() const; virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; +#endif void set_polygon(const PoolVector<Vector2> &p_polygon); PoolVector<Vector2> get_polygon() const; diff --git a/scene/2d/position_2d.cpp b/scene/2d/position_2d.cpp index e37407ceb3..cdeb905c0c 100644 --- a/scene/2d/position_2d.cpp +++ b/scene/2d/position_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -43,6 +43,7 @@ void Position2D::_draw_cross() { draw_line(Point2(0, -extents), Point2(0, +extents), Color(0.53, 0.84, 0.01)); } +#ifdef TOOLS_ENABLED Rect2 Position2D::_edit_get_rect() const { float extents = get_gizmo_extents(); @@ -52,6 +53,7 @@ Rect2 Position2D::_edit_get_rect() const { bool Position2D::_edit_use_rect() const { return false; } +#endif void Position2D::_notification(int p_what) { diff --git a/scene/2d/position_2d.h b/scene/2d/position_2d.h index f5ec3ef01a..3ea636171d 100644 --- a/scene/2d/position_2d.h +++ b/scene/2d/position_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -44,8 +44,10 @@ protected: static void _bind_methods(); public: +#ifdef TOOLS_ENABLED virtual Rect2 _edit_get_rect() const; virtual bool _edit_use_rect() const; +#endif void set_gizmo_extents(float p_extents); float get_gizmo_extents() const; diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp index bf8d008bb2..5098d5115a 100644 --- a/scene/2d/ray_cast_2d.cpp +++ b/scene/2d/ray_cast_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -180,8 +180,8 @@ void RayCast2D::_notification(int p_what) { Vector<Vector2> pts; float tsize = 8; pts.push_back(xf.xform(Vector2(tsize, 0))); - pts.push_back(xf.xform(Vector2(0, 0.707 * tsize))); - pts.push_back(xf.xform(Vector2(0, -0.707 * tsize))); + pts.push_back(xf.xform(Vector2(0, Math_SQRT12 * tsize))); + pts.push_back(xf.xform(Vector2(0, -Math_SQRT12 * tsize))); Vector<Color> cols; for (int i = 0; i < 3; i++) cols.push_back(draw_col); diff --git a/scene/2d/ray_cast_2d.h b/scene/2d/ray_cast_2d.h index f53f3ff07b..20f05e7525 100644 --- a/scene/2d/ray_cast_2d.h +++ b/scene/2d/ray_cast_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/remote_transform_2d.cpp b/scene/2d/remote_transform_2d.cpp index fe8cc5a5fc..53072f942d 100644 --- a/scene/2d/remote_transform_2d.cpp +++ b/scene/2d/remote_transform_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/remote_transform_2d.h b/scene/2d/remote_transform_2d.h index e85fe33fc6..f5b949d10b 100644 --- a/scene/2d/remote_transform_2d.h +++ b/scene/2d/remote_transform_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp index bf43fca864..6f64464cc9 100644 --- a/scene/2d/skeleton_2d.cpp +++ b/scene/2d/skeleton_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/skeleton_2d.h b/scene/2d/skeleton_2d.h index 0f48b44387..c6bee8d92b 100644 --- a/scene/2d/skeleton_2d.h +++ b/scene/2d/skeleton_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp index 8cdfceea52..55daed0585 100644 --- a/scene/2d/sprite.cpp +++ b/scene/2d/sprite.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -34,6 +34,7 @@ #include "scene/main/viewport.h" #include "scene/scene_string_names.h" +#ifdef TOOLS_ENABLED Dictionary Sprite::_edit_get_state() const { Dictionary state = Node2D::_edit_get_state(); state["offset"] = offset; @@ -58,6 +59,11 @@ bool Sprite::_edit_use_pivot() const { return true; } +bool Sprite::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { + + return is_pixel_opaque(p_point); +} + Rect2 Sprite::_edit_get_rect() const { return get_rect(); } @@ -65,6 +71,7 @@ Rect2 Sprite::_edit_get_rect() const { bool Sprite::_edit_use_rect() const { return texture.is_valid(); } +#endif Rect2 Sprite::get_anchorable_rect() const { return get_rect(); @@ -305,16 +312,14 @@ int Sprite::get_hframes() const { return hframes; } -bool Sprite::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { - - return is_pixel_opaque(p_point); -} - bool Sprite::is_pixel_opaque(const Point2 &p_point) const { if (texture.is_null()) return false; + if (texture->get_size().width == 0 || texture->get_size().height == 0) + return false; + Rect2 src_rect, dst_rect; bool filter_clip; _get_rects(src_rect, dst_rect, filter_clip); diff --git a/scene/2d/sprite.h b/scene/2d/sprite.h index d3c0112e62..d72bf3168d 100644 --- a/scene/2d/sprite.h +++ b/scene/2d/sprite.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -67,6 +67,7 @@ protected: virtual void _validate_property(PropertyInfo &property) const; public: +#ifdef TOOLS_ENABLED virtual Dictionary _edit_get_state() const; virtual void _edit_set_state(const Dictionary &p_state); @@ -75,10 +76,11 @@ public: virtual bool _edit_use_pivot() const; virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; - bool is_pixel_opaque(const Point2 &p_point) const; - virtual Rect2 _edit_get_rect() const; virtual bool _edit_use_rect() const; +#endif + + bool is_pixel_opaque(const Point2 &p_point) const; void set_texture(const Ref<Texture> &p_texture); Ref<Texture> get_texture() const; diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 173214dfe4..d8b880e571 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -35,6 +35,7 @@ #include "core/method_bind_ext.gen.inc" #include "core/os/os.h" #include "scene/2d/area_2d.h" +#include "servers/navigation_2d_server.h" #include "servers/physics_2d_server.h" int TileMap::_get_quadrant_size() const { @@ -86,7 +87,7 @@ void TileMap::_notification(int p_what) { if (navigation) { for (Map<PosKey, Quadrant::NavPoly>::Element *F = q.navpoly_ids.front(); F; F = F->next()) { - navigation->navpoly_remove(F->get().id); + Navigation2DServer::get_singleton()->region_set_map(F->get().region, RID()); } q.navpoly_ids.clear(); } @@ -163,7 +164,7 @@ void TileMap::_update_quadrant_transform() { if (navigation) { for (Map<PosKey, Quadrant::NavPoly>::Element *F = q.navpoly_ids.front(); F; F = F->next()) { - navigation->navpoly_set_transform(F->get().id, nav_rel * F->get().xform); + Navigation2DServer::get_singleton()->region_set_transform(F->get().region, nav_rel * F->get().xform); } } @@ -377,7 +378,7 @@ void TileMap::update_dirty_quadrants() { if (navigation) { for (Map<PosKey, Quadrant::NavPoly>::Element *E = q.navpoly_ids.front(); E; E = E->next()) { - navigation->navpoly_remove(E->get().id); + Navigation2DServer::get_singleton()->region_set_map(E->get().region, RID()); } q.navpoly_ids.clear(); } @@ -611,10 +612,13 @@ void TileMap::update_dirty_quadrants() { xform.set_origin(offset.floor() + q.pos); _fix_cell_transform(xform, c, npoly_ofs, s); - int pid = navigation->navpoly_add(navpoly, nav_rel * xform); + RID region = Navigation2DServer::get_singleton()->region_create(); + Navigation2DServer::get_singleton()->region_set_map(region, navigation->get_rid()); + Navigation2DServer::get_singleton()->region_set_transform(region, nav_rel * xform); + Navigation2DServer::get_singleton()->region_set_navpoly(region, navpoly); Quadrant::NavPoly np; - np.id = pid; + np.region = region; np.xform = xform; q.navpoly_ids[E->key()] = np; @@ -809,7 +813,7 @@ void TileMap::_erase_quadrant(Map<PosKey, Quadrant>::Element *Q) { if (navigation) { for (Map<PosKey, Quadrant::NavPoly>::Element *E = q.navpoly_ids.front(); E; E = E->next()) { - navigation->navpoly_remove(E->get().id); + Navigation2DServer::get_singleton()->region_set_map(E->get().region, RID()); } q.navpoly_ids.clear(); } @@ -1233,8 +1237,8 @@ void TileMap::_set_tile_data(const PoolVector<int> &p_data) { } #endif - int16_t x = decode_uint16(&local[0]); - int16_t y = decode_uint16(&local[2]); + uint16_t x = decode_uint16(&local[0]); + uint16_t y = decode_uint16(&local[2]); uint32_t v = decode_uint32(&local[4]); bool flip_h = v & (1 << 29); bool flip_v = v & (1 << 30); @@ -1282,6 +1286,7 @@ PoolVector<int> TileMap::_get_tile_data() const { return data; } +#ifdef TOOLS_ENABLED Rect2 TileMap::_edit_get_rect() const { if (pending_update) { const_cast<TileMap *>(this)->update_dirty_quadrants(); @@ -1290,6 +1295,7 @@ Rect2 TileMap::_edit_get_rect() const { } return rect_cache; } +#endif void TileMap::set_collision_layer(uint32_t p_layer) { diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index e30b7eff83..d5ef7fc818 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -139,7 +139,7 @@ private: SelfList<Quadrant> dirty_list; struct NavPoly { - int id; + RID region; Transform2D xform; }; @@ -244,7 +244,9 @@ public: INVALID_CELL = -1 }; +#ifdef TOOLS_ENABLED virtual Rect2 _edit_get_rect() const; +#endif void set_tileset(const Ref<TileSet> &p_tileset); Ref<TileSet> get_tileset() const; diff --git a/scene/2d/touch_screen_button.cpp b/scene/2d/touch_screen_button.cpp index 9a1a759e72..42d9f88a60 100644 --- a/scene/2d/touch_screen_button.cpp +++ b/scene/2d/touch_screen_button.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -135,7 +135,9 @@ void TouchScreenButton::_notification(int p_what) { return; if (shape.is_valid()) { Color draw_col = get_tree()->get_debug_collisions_color(); - Vector2 pos = shape_centered ? _edit_get_rect().size * 0.5f : Vector2(); + + Vector2 size = texture.is_null() ? shape->get_rect().size : texture->get_size(); + Vector2 pos = shape_centered ? size * 0.5f : Vector2(); draw_set_transform_matrix(get_canvas_transform().translated(pos)); shape->draw(get_canvas_item(), draw_col); } @@ -251,9 +253,7 @@ void TouchScreenButton::_input(const Ref<InputEvent> &p_event) { } bool TouchScreenButton::_is_point_inside(const Point2 &p_point) { - Point2 coord = (get_global_transform_with_canvas()).affine_inverse().xform(p_point); - Rect2 item_rect = _edit_get_rect(); bool touched = false; bool check_rect = true; @@ -261,7 +261,7 @@ bool TouchScreenButton::_is_point_inside(const Point2 &p_point) { if (shape.is_valid()) { check_rect = false; - Transform2D xform = shape_centered ? Transform2D().translated(item_rect.size * 0.5f) : Transform2D(); + Transform2D xform = shape_centered ? Transform2D().translated(shape->get_rect().size * 0.5f) : Transform2D(); touched = shape->collide(xform, unit_rect, Transform2D(0, coord + Vector2(0.5, 0.5))); } @@ -277,7 +277,7 @@ bool TouchScreenButton::_is_point_inside(const Point2 &p_point) { if (!touched && check_rect) { if (texture.is_valid()) - touched = item_rect.has_point(coord); + touched = Rect2(Size2(), texture->get_size()).has_point(coord); } return touched; @@ -324,6 +324,7 @@ void TouchScreenButton::_release(bool p_exiting_tree) { } } +#ifdef TOOLS_ENABLED Rect2 TouchScreenButton::_edit_get_rect() const { if (texture.is_null()) return CanvasItem::_edit_get_rect(); @@ -334,6 +335,7 @@ Rect2 TouchScreenButton::_edit_get_rect() const { bool TouchScreenButton::_edit_use_rect() const { return !texture.is_null(); } +#endif Rect2 TouchScreenButton::get_anchorable_rect() const { if (texture.is_null()) diff --git a/scene/2d/touch_screen_button.h b/scene/2d/touch_screen_button.h index df54e5340b..28dba59402 100644 --- a/scene/2d/touch_screen_button.h +++ b/scene/2d/touch_screen_button.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -74,6 +74,11 @@ protected: static void _bind_methods(); public: +#ifdef TOOLS_ENABLED + virtual Rect2 _edit_get_rect() const; + virtual bool _edit_use_rect() const; +#endif + void set_texture(const Ref<Texture> &p_texture); Ref<Texture> get_texture() const; @@ -103,8 +108,6 @@ public: bool is_pressed() 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/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp index a1d074e6cd..0ac725b7dd 100644 --- a/scene/2d/visibility_notifier_2d.cpp +++ b/scene/2d/visibility_notifier_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -38,6 +38,16 @@ #include "scene/main/viewport.h" #include "scene/scene_string_names.h" +#ifdef TOOLS_ENABLED +Rect2 VisibilityNotifier2D::_edit_get_rect() const { + return rect; +} + +bool VisibilityNotifier2D::_edit_use_rect() const { + return true; +} +#endif + void VisibilityNotifier2D::_enter_viewport(Viewport *p_viewport) { ERR_FAIL_COND(viewports.has(p_viewport)); @@ -84,15 +94,6 @@ void VisibilityNotifier2D::set_rect(const Rect2 &p_rect) { _change_notify("rect"); } -Rect2 VisibilityNotifier2D::_edit_get_rect() const { - - return rect; -} - -bool VisibilityNotifier2D::_edit_use_rect() const { - return true; -} - Rect2 VisibilityNotifier2D::get_rect() const { return rect; @@ -319,8 +320,6 @@ void VisibilityEnabler2D::_node_removed(Node *p_node) { if (!visible) _change_node_state(p_node, true); - //changed to one shot, not needed - //p_node->disconnect(SceneStringNames::get_singleton()->exit_scene,this,"_node_removed"); nodes.erase(p_node); } diff --git a/scene/2d/visibility_notifier_2d.h b/scene/2d/visibility_notifier_2d.h index 259368455b..a3b79d29e9 100644 --- a/scene/2d/visibility_notifier_2d.h +++ b/scene/2d/visibility_notifier_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -55,8 +55,10 @@ protected: static void _bind_methods(); public: +#ifdef TOOLS_ENABLED virtual Rect2 _edit_get_rect() const; virtual bool _edit_use_rect() const; +#endif void set_rect(const Rect2 &p_rect); Rect2 get_rect() const; diff --git a/scene/2d/y_sort.cpp b/scene/2d/y_sort.cpp index d7e523e189..62f10a5c96 100644 --- a/scene/2d/y_sort.cpp +++ b/scene/2d/y_sort.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/y_sort.h b/scene/2d/y_sort.h index 1bf757720e..62787d6744 100644 --- a/scene/2d/y_sort.h +++ b/scene/2d/y_sort.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp index 77682abcb3..67f57a1aa3 100644 --- a/scene/3d/area.cpp +++ b/scene/3d/area.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/area.h b/scene/3d/area.h index 043d651e04..ca66f41f60 100644 --- a/scene/3d/area.h +++ b/scene/3d/area.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/arvr_nodes.cpp b/scene/3d/arvr_nodes.cpp index 4c0449b68e..8d1556ef1c 100644 --- a/scene/3d/arvr_nodes.cpp +++ b/scene/3d/arvr_nodes.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -85,9 +85,8 @@ Vector3 ARVRCamera::project_local_ray_normal(const Point2 &p_pos) const { Vector3 ray; CameraMatrix cm = arvr_interface->get_projection_for_eye(ARVRInterface::EYE_MONO, viewport_size.aspect(), get_znear(), get_zfar()); - float screen_w, screen_h; - cm.get_viewport_size(screen_w, screen_h); - ray = Vector3(((cpos.x / viewport_size.width) * 2.0 - 1.0) * screen_w, ((1.0 - (cpos.y / viewport_size.height)) * 2.0 - 1.0) * screen_h, -get_znear()).normalized(); + Vector2 screen_he = cm.get_viewport_half_extents(); + ray = Vector3(((cpos.x / viewport_size.width) * 2.0 - 1.0) * screen_he.x, ((1.0 - (cpos.y / viewport_size.height)) * 2.0 - 1.0) * screen_he.y, -get_znear()).normalized(); return ray; }; @@ -138,13 +137,12 @@ Vector3 ARVRCamera::project_position(const Point2 &p_point, float p_z_depth) con CameraMatrix cm = arvr_interface->get_projection_for_eye(ARVRInterface::EYE_MONO, viewport_size.aspect(), get_znear(), get_zfar()); - Size2 vp_size; - cm.get_viewport_size(vp_size.x, vp_size.y); + Vector2 vp_he = cm.get_viewport_half_extents(); Vector2 point; point.x = (p_point.x / viewport_size.x) * 2.0 - 1.0; point.y = (1.0 - (p_point.y / viewport_size.y)) * 2.0 - 1.0; - point *= vp_size; + point *= vp_he; Vector3 p(point.x, point.y, -p_z_depth); @@ -295,7 +293,8 @@ int ARVRController::get_joystick_id() const { ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, controller_id); if (tracker == NULL) { - return 0; + // No tracker? no joystick id... (0 is our first joystick) + return -1; }; return tracker->get_joy_id(); diff --git a/scene/3d/arvr_nodes.h b/scene/3d/arvr_nodes.h index b647df70aa..44dfda15a6 100644 --- a/scene/3d/arvr_nodes.h +++ b/scene/3d/arvr_nodes.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index 05ae281cc1..596ef78fb5 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/audio_stream_player_3d.h b/scene/3d/audio_stream_player_3d.h index 494aa70097..5b4c865475 100644 --- a/scene/3d/audio_stream_player_3d.h +++ b/scene/3d/audio_stream_player_3d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/baked_lightmap.cpp b/scene/3d/baked_lightmap.cpp index 4b1eccb40d..071afd1a69 100644 --- a/scene/3d/baked_lightmap.cpp +++ b/scene/3d/baked_lightmap.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -360,7 +360,7 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, bool p_create_vi //check for valid save path DirAccessRef d = DirAccess::open(save_path); if (!d) { - ERR_PRINTS("Invalid Save Path '" + save_path + "'."); + ERR_PRINT("Invalid Save Path '" + save_path + "'."); return BAKE_ERROR_NO_SAVE_PATH; } } diff --git a/scene/3d/baked_lightmap.h b/scene/3d/baked_lightmap.h index 3a9f4cf01d..82354cc9f0 100644 --- a/scene/3d/baked_lightmap.h +++ b/scene/3d/baked_lightmap.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/bone_attachment.cpp b/scene/3d/bone_attachment.cpp index 0233029435..e94e174b92 100644 --- a/scene/3d/bone_attachment.cpp +++ b/scene/3d/bone_attachment.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/bone_attachment.h b/scene/3d/bone_attachment.h index 051e2b4c56..43c46dd759 100644 --- a/scene/3d/bone_attachment.h +++ b/scene/3d/bone_attachment.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp index 4d9bb69778..640189a26e 100644 --- a/scene/3d/camera.cpp +++ b/scene/3d/camera.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -291,9 +291,8 @@ Vector3 Camera::project_local_ray_normal(const Point2 &p_pos) const { } else { CameraMatrix cm; cm.set_perspective(fov, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH); - float screen_w, screen_h; - cm.get_viewport_size(screen_w, screen_h); - ray = Vector3(((cpos.x / viewport_size.width) * 2.0 - 1.0) * screen_w, ((1.0 - (cpos.y / viewport_size.height)) * 2.0 - 1.0) * screen_h, -near).normalized(); + Vector2 screen_he = cm.get_viewport_half_extents(); + ray = Vector3(((cpos.x / viewport_size.width) * 2.0 - 1.0) * screen_he.x, ((1.0 - (cpos.y / viewport_size.height)) * 2.0 - 1.0) * screen_he.y, -near).normalized(); } return ray; @@ -390,26 +389,24 @@ Vector3 Camera::project_position(const Point2 &p_point, float p_z_depth) const { ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector3(), "Camera is not inside scene."); - if (p_z_depth == 0) { + if (p_z_depth == 0 && mode != PROJECTION_ORTHOGONAL) { return get_global_transform().origin; } - Size2 viewport_size = get_viewport()->get_visible_rect().size; CameraMatrix cm; if (mode == PROJECTION_ORTHOGONAL) - cm.set_orthogonal(size, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH); + cm.set_orthogonal(size, viewport_size.aspect(), p_z_depth, far, keep_aspect == KEEP_WIDTH); else - cm.set_perspective(fov, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH); + cm.set_perspective(fov, viewport_size.aspect(), p_z_depth, far, keep_aspect == KEEP_WIDTH); - Size2 vp_size; - cm.get_viewport_size(vp_size.x, vp_size.y); + Vector2 vp_he = cm.get_viewport_half_extents(); Vector2 point; point.x = (p_point.x / viewport_size.x) * 2.0 - 1.0; point.y = (1.0 - (p_point.y / viewport_size.y)) * 2.0 - 1.0; - point *= vp_size; + point *= vp_he; Vector3 p(point.x, point.y, -p_z_depth); @@ -583,12 +580,14 @@ Camera::Projection Camera::get_projection() const { } void Camera::set_fov(float p_fov) { + ERR_FAIL_COND(p_fov < 1 || p_fov > 179); fov = p_fov; _update_camera_mode(); _change_notify("fov"); } void Camera::set_size(float p_size) { + ERR_FAIL_COND(p_size < 0.1 || p_size > 16384); size = p_size; _update_camera_mode(); _change_notify("size"); diff --git a/scene/3d/camera.h b/scene/3d/camera.h index d81e097fc5..e215783a58 100644 --- a/scene/3d/camera.h +++ b/scene/3d/camera.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/collision_object.cpp b/scene/3d/collision_object.cpp index 735b393171..c067ef34a6 100644 --- a/scene/3d/collision_object.cpp +++ b/scene/3d/collision_object.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/collision_object.h b/scene/3d/collision_object.h index 90f370b6d4..572e73d51b 100644 --- a/scene/3d/collision_object.h +++ b/scene/3d/collision_object.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/collision_polygon.cpp b/scene/3d/collision_polygon.cpp index 37aa95fb43..cc07072962 100644 --- a/scene/3d/collision_polygon.cpp +++ b/scene/3d/collision_polygon.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -44,7 +44,7 @@ void CollisionPolygon::_build_polygon() { if (polygon.size() == 0) return; - Vector<Vector<Vector2> > decomp = Geometry::decompose_polygon(polygon); + Vector<Vector<Vector2> > decomp = Geometry::decompose_polygon_in_convex(polygon); if (decomp.size() == 0) return; diff --git a/scene/3d/collision_polygon.h b/scene/3d/collision_polygon.h index 04c00fc70f..9ecdc02697 100644 --- a/scene/3d/collision_polygon.h +++ b/scene/3d/collision_polygon.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/collision_shape.cpp b/scene/3d/collision_shape.cpp index 2b030641eb..bf2816fd41 100644 --- a/scene/3d/collision_shape.cpp +++ b/scene/3d/collision_shape.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/collision_shape.h b/scene/3d/collision_shape.h index 98427b8590..3150a41ebf 100644 --- a/scene/3d/collision_shape.h +++ b/scene/3d/collision_shape.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/cpu_particles.cpp b/scene/3d/cpu_particles.cpp index 86daabefd2..aa7a413548 100644 --- a/scene/3d/cpu_particles.cpp +++ b/scene/3d/cpu_particles.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -405,7 +405,7 @@ bool CPUParticles::get_particle_flag(Flags p_flag) const { } void CPUParticles::set_emission_shape(EmissionShape p_shape) { - + ERR_FAIL_INDEX(p_shape, EMISSION_SHAPE_MAX); emission_shape = p_shape; } @@ -784,6 +784,9 @@ void CPUParticles::_particles_process(float p_delta) { p.base_color = emission_colors.get(random_idx); } } break; + case EMISSION_SHAPE_MAX: { // Max value for validity check. + break; + } } if (!local_coords) { @@ -1488,6 +1491,7 @@ void CPUParticles::_bind_methods() { BIND_ENUM_CONSTANT(EMISSION_SHAPE_BOX); BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINTS); BIND_ENUM_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS); + BIND_ENUM_CONSTANT(EMISSION_SHAPE_MAX); } CPUParticles::CPUParticles() { diff --git a/scene/3d/cpu_particles.h b/scene/3d/cpu_particles.h index 635265be7f..d5a549b976 100644 --- a/scene/3d/cpu_particles.h +++ b/scene/3d/cpu_particles.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -75,6 +75,7 @@ public: EMISSION_SHAPE_BOX, EMISSION_SHAPE_POINTS, EMISSION_SHAPE_DIRECTED_POINTS, + EMISSION_SHAPE_MAX }; private: diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp index ccc87b924c..99bc78f5d2 100644 --- a/scene/3d/gi_probe.cpp +++ b/scene/3d/gi_probe.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -386,11 +386,7 @@ void GIProbe::_find_meshes(Node *p_at_node, List<PlotMesh> &plot_meshes) { } for (int i = 0; i < p_at_node->get_child_count(); i++) { - Node *child = p_at_node->get_child(i); - if (!child->get_owner()) - continue; //maybe a helper - _find_meshes(child, plot_meshes); } } diff --git a/scene/3d/gi_probe.h b/scene/3d/gi_probe.h index 4badabbadf..7c58f862e4 100644 --- a/scene/3d/gi_probe.h +++ b/scene/3d/gi_probe.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/immediate_geometry.cpp b/scene/3d/immediate_geometry.cpp index a555106bd8..0a1beaf3f4 100644 --- a/scene/3d/immediate_geometry.cpp +++ b/scene/3d/immediate_geometry.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/immediate_geometry.h b/scene/3d/immediate_geometry.h index 3467663dff..f45ebd6724 100644 --- a/scene/3d/immediate_geometry.h +++ b/scene/3d/immediate_geometry.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/interpolated_camera.cpp b/scene/3d/interpolated_camera.cpp index d720dd117c..baf5ac4be6 100644 --- a/scene/3d/interpolated_camera.cpp +++ b/scene/3d/interpolated_camera.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/interpolated_camera.h b/scene/3d/interpolated_camera.h index 97100c9501..7b160c66fa 100644 --- a/scene/3d/interpolated_camera.h +++ b/scene/3d/interpolated_camera.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp index 85ee925248..593d0b95b7 100644 --- a/scene/3d/light.cpp +++ b/scene/3d/light.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -103,6 +103,8 @@ void Light::set_color(const Color &p_color) { color = p_color; VS::get_singleton()->light_set_color(light, p_color); + // The gizmo color depends on the light color, so update it. + update_gizmo(); } Color Light::get_color() const { diff --git a/scene/3d/light.h b/scene/3d/light.h index cc8675ead1..272ee8d7a9 100644 --- a/scene/3d/light.h +++ b/scene/3d/light.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/listener.cpp b/scene/3d/listener.cpp index 85e65e23f2..2779d14b57 100644 --- a/scene/3d/listener.cpp +++ b/scene/3d/listener.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/listener.h b/scene/3d/listener.h index 86451e7d99..287e67f31e 100644 --- a/scene/3d/listener.h +++ b/scene/3d/listener.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp index 50ca466df3..e14fa9e9af 100644 --- a/scene/3d/mesh_instance.cpp +++ b/scene/3d/mesh_instance.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -154,10 +154,10 @@ void MeshInstance::_resolve_skeleton_path() { if (!skeleton_path.is_empty()) { Skeleton *skeleton = Object::cast_to<Skeleton>(get_node(skeleton_path)); if (skeleton) { - new_skin_reference = skeleton->register_skin(skin); - if (skin.is_null()) { + new_skin_reference = skeleton->register_skin(skin_internal); + if (skin_internal.is_null()) { //a skin was created for us - skin = new_skin_reference->get_skin(); + skin_internal = new_skin_reference->get_skin(); _change_notify(); } } @@ -173,6 +173,7 @@ void MeshInstance::_resolve_skeleton_path() { } void MeshInstance::set_skin(const Ref<Skin> &p_skin) { + skin_internal = p_skin; skin = p_skin; if (!is_inside_tree()) return; diff --git a/scene/3d/mesh_instance.h b/scene/3d/mesh_instance.h index 77ead75dd3..fd5f60a5d7 100644 --- a/scene/3d/mesh_instance.h +++ b/scene/3d/mesh_instance.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -43,6 +43,7 @@ class MeshInstance : public GeometryInstance { protected: Ref<Mesh> mesh; Ref<Skin> skin; + Ref<Skin> skin_internal; Ref<SkinReference> skin_ref; NodePath skeleton_path; diff --git a/scene/3d/multimesh_instance.cpp b/scene/3d/multimesh_instance.cpp index d744a74859..245dbdaf58 100644 --- a/scene/3d/multimesh_instance.cpp +++ b/scene/3d/multimesh_instance.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/multimesh_instance.h b/scene/3d/multimesh_instance.h index ca69c73251..855bd54910 100644 --- a/scene/3d/multimesh_instance.h +++ b/scene/3d/multimesh_instance.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/navigation.cpp b/scene/3d/navigation.cpp index ba0460d47c..10b12f5c75 100644 --- a/scene/3d/navigation.cpp +++ b/scene/3d/navigation.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,698 +30,76 @@ #include "navigation.h" -#define USE_ENTRY_POINT +#include "servers/navigation_server.h" -void Navigation::_navmesh_link(int p_id) { - - ERR_FAIL_COND(!navmesh_map.has(p_id)); - NavMesh &nm = navmesh_map[p_id]; - ERR_FAIL_COND(nm.linked); - ERR_FAIL_COND(nm.navmesh.is_null()); - - PoolVector<Vector3> vertices = nm.navmesh->get_vertices(); - int len = vertices.size(); - if (len == 0) - return; - - PoolVector<Vector3>::Read r = vertices.read(); - - for (int i = 0; i < nm.navmesh->get_polygon_count(); i++) { - - //build - - List<Polygon>::Element *P = nm.polygons.push_back(Polygon()); - Polygon &p = P->get(); - p.owner = &nm; - - Vector<int> poly = nm.navmesh->get_polygon(i); - int plen = poly.size(); - const int *indices = poly.ptr(); - bool valid = true; - p.edges.resize(plen); - - Vector3 center; - float sum = 0; - - for (int j = 0; j < plen; j++) { - - int idx = indices[j]; - if (idx < 0 || idx >= len) { - valid = false; - break; - } - - Polygon::Edge e; - Vector3 ep = nm.xform.xform(r[idx]); - center += ep; - e.point = _get_point(ep); - p.edges.write[j] = e; - - if (j >= 2) { - Vector3 epa = nm.xform.xform(r[indices[j - 2]]); - Vector3 epb = nm.xform.xform(r[indices[j - 1]]); - - sum += up.dot((epb - epa).cross(ep - epa)); - } - } - - p.clockwise = sum > 0; - - if (!valid) { - nm.polygons.pop_back(); - ERR_CONTINUE(!valid); - } - - p.center = center; - if (plen != 0) { - p.center /= plen; - } - - //connect - - for (int j = 0; j < plen; j++) { - - int next = (j + 1) % plen; - EdgeKey ek(p.edges[j].point, p.edges[next].point); - - Map<EdgeKey, Connection>::Element *C = connections.find(ek); - if (!C) { - - Connection c; - c.A = &p; - c.A_edge = j; - c.B = NULL; - c.B_edge = -1; - connections[ek] = c; - } else { - - if (C->get().B != NULL) { - ConnectionPending pending; - pending.polygon = &p; - pending.edge = j; - p.edges.write[j].P = C->get().pending.push_back(pending); - continue; - } - - C->get().B = &p; - C->get().B_edge = j; - C->get().A->edges.write[C->get().A_edge].C = &p; - C->get().A->edges.write[C->get().A_edge].C_edge = j; - p.edges.write[j].C = C->get().A; - p.edges.write[j].C_edge = C->get().A_edge; - //connection successful. - } - } - } - - nm.linked = true; -} - -void Navigation::_navmesh_unlink(int p_id) { - - ERR_FAIL_COND(!navmesh_map.has(p_id)); - NavMesh &nm = navmesh_map[p_id]; - ERR_FAIL_COND(!nm.linked); - - for (List<Polygon>::Element *E = nm.polygons.front(); E; E = E->next()) { - - Polygon &p = E->get(); - - int ec = p.edges.size(); - Polygon::Edge *edges = p.edges.ptrw(); - - for (int i = 0; i < ec; i++) { - int next = (i + 1) % ec; - - EdgeKey ek(edges[i].point, edges[next].point); - Map<EdgeKey, Connection>::Element *C = connections.find(ek); - - ERR_CONTINUE(!C); - - if (edges[i].P) { - C->get().pending.erase(edges[i].P); - edges[i].P = NULL; - } else if (C->get().B) { - //disconnect - - C->get().B->edges.write[C->get().B_edge].C = NULL; - C->get().B->edges.write[C->get().B_edge].C_edge = -1; - C->get().A->edges.write[C->get().A_edge].C = NULL; - C->get().A->edges.write[C->get().A_edge].C_edge = -1; - - if (C->get().A == &E->get()) { - - C->get().A = C->get().B; - C->get().A_edge = C->get().B_edge; - } - C->get().B = NULL; - C->get().B_edge = -1; - - if (C->get().pending.size()) { - //reconnect if something is pending - ConnectionPending cp = C->get().pending.front()->get(); - C->get().pending.pop_front(); - - C->get().B = cp.polygon; - C->get().B_edge = cp.edge; - C->get().A->edges.write[C->get().A_edge].C = cp.polygon; - C->get().A->edges.write[C->get().A_edge].C_edge = cp.edge; - cp.polygon->edges.write[cp.edge].C = C->get().A; - cp.polygon->edges.write[cp.edge].C_edge = C->get().A_edge; - cp.polygon->edges.write[cp.edge].P = NULL; - } - - } else { - connections.erase(C); - //erase - } - } - } - - nm.polygons.clear(); - - nm.linked = false; -} - -int Navigation::navmesh_add(const Ref<NavigationMesh> &p_mesh, const Transform &p_xform, Object *p_owner) { - - int id = last_id++; - NavMesh nm; - nm.linked = false; - nm.navmesh = p_mesh; - nm.xform = p_xform; - nm.owner = p_owner; - navmesh_map[id] = nm; - - _navmesh_link(id); - - return id; -} - -void Navigation::navmesh_set_transform(int p_id, const Transform &p_xform) { - - ERR_FAIL_COND(!navmesh_map.has(p_id)); - NavMesh &nm = navmesh_map[p_id]; - if (nm.xform == p_xform) - return; //bleh - _navmesh_unlink(p_id); - nm.xform = p_xform; - _navmesh_link(p_id); -} -void Navigation::navmesh_remove(int p_id) { +Vector<Vector3> Navigation::get_simple_path(const Vector3 &p_start, const Vector3 &p_end, bool p_optimize) { - ERR_FAIL_COND_MSG(!navmesh_map.has(p_id), "Trying to remove nonexisting navmesh with id: " + itos(p_id)); - _navmesh_unlink(p_id); - navmesh_map.erase(p_id); + return NavigationServer::get_singleton()->map_get_path(map, p_start, p_end, p_optimize); } -void Navigation::_clip_path(Vector<Vector3> &path, Polygon *from_poly, const Vector3 &p_to_point, Polygon *p_to_poly) { - - Vector3 from = path[path.size() - 1]; - - if (from.distance_to(p_to_point) < CMP_EPSILON) - return; - Plane cut_plane; - cut_plane.normal = (from - p_to_point).cross(up); - if (cut_plane.normal == Vector3()) - return; - cut_plane.normal.normalize(); - cut_plane.d = cut_plane.normal.dot(from); - - while (from_poly != p_to_poly) { - - int pe = from_poly->prev_edge; - Vector3 a = _get_vertex(from_poly->edges[pe].point); - Vector3 b = _get_vertex(from_poly->edges[(pe + 1) % from_poly->edges.size()].point); - - from_poly = from_poly->edges[pe].C; - ERR_FAIL_COND(!from_poly); - - if (a.distance_to(b) > CMP_EPSILON) { +void Navigation::set_up_vector(const Vector3 &p_up) { - Vector3 inters; - if (cut_plane.intersects_segment(a, b, &inters)) { - if (inters.distance_to(p_to_point) > CMP_EPSILON && inters.distance_to(path[path.size() - 1]) > CMP_EPSILON) { - path.push_back(inters); - } - } - } - } + up = p_up; + NavigationServer::get_singleton()->map_set_up(map, up); } -Vector<Vector3> Navigation::get_simple_path(const Vector3 &p_start, const Vector3 &p_end, bool p_optimize) { - - Polygon *begin_poly = NULL; - Polygon *end_poly = NULL; - Vector3 begin_point; - Vector3 end_point; - float begin_d = 1e20; - float end_d = 1e20; - - for (Map<int, NavMesh>::Element *E = navmesh_map.front(); E; E = E->next()) { - - if (!E->get().linked) - continue; - for (List<Polygon>::Element *F = E->get().polygons.front(); F; F = F->next()) { - - Polygon &p = F->get(); - for (int i = 2; i < p.edges.size(); i++) { - - Face3 f(_get_vertex(p.edges[0].point), _get_vertex(p.edges[i - 1].point), _get_vertex(p.edges[i].point)); - Vector3 spoint = f.get_closest_point_to(p_start); - float dpoint = spoint.distance_to(p_start); - if (dpoint < begin_d) { - begin_d = dpoint; - begin_poly = &p; - begin_point = spoint; - } - - spoint = f.get_closest_point_to(p_end); - dpoint = spoint.distance_to(p_end); - if (dpoint < end_d) { - end_d = dpoint; - end_poly = &p; - end_point = spoint; - } - } - - p.prev_edge = -1; - } - } - - if (!begin_poly || !end_poly) { - - return Vector<Vector3>(); //no path - } - - if (begin_poly == end_poly) { - - Vector<Vector3> path; - path.resize(2); - path.write[0] = begin_point; - path.write[1] = end_point; - return path; - } - - bool found_route = false; - - List<Polygon *> open_list; - - for (int i = 0; i < begin_poly->edges.size(); i++) { - - if (begin_poly->edges[i].C) { - - begin_poly->edges[i].C->prev_edge = begin_poly->edges[i].C_edge; -#ifdef USE_ENTRY_POINT - Vector3 edge[2] = { - _get_vertex(begin_poly->edges[i].point), - _get_vertex(begin_poly->edges[(i + 1) % begin_poly->edges.size()].point) - }; - - Vector3 entry = Geometry::get_closest_point_to_segment(begin_poly->entry, edge); - begin_poly->edges[i].C->distance = begin_point.distance_to(entry); - begin_poly->edges[i].C->entry = entry; -#else - begin_poly->edges[i].C->distance = begin_poly->center.distance_to(begin_poly->edges[i].C->center); -#endif - open_list.push_back(begin_poly->edges[i].C); - } - } - - while (!found_route) { - - if (open_list.size() == 0) { - break; - } - //check open list - - List<Polygon *>::Element *least_cost_poly = NULL; - float least_cost = 1e30; - - //this could be faster (cache previous results) - for (List<Polygon *>::Element *E = open_list.front(); E; E = E->next()) { - - Polygon *p = E->get(); - - float cost = p->distance; -#ifdef USE_ENTRY_POINT - cost += p->entry.distance_to(end_point); -#else - cost += p->center.distance_to(end_point); -#endif - if (cost < least_cost) { - least_cost_poly = E; - least_cost = cost; - } - } - - Polygon *p = least_cost_poly->get(); - //open the neighbours for search - - if (p == end_poly) { - //oh my reached end! stop algorithm - found_route = true; - break; - } - - for (int i = 0; i < p->edges.size(); i++) { - - Polygon::Edge &e = p->edges.write[i]; - - if (!e.C) - continue; - -#ifdef USE_ENTRY_POINT - Vector3 edge[2] = { - _get_vertex(p->edges[i].point), - _get_vertex(p->edges[(i + 1) % p->edges.size()].point) - }; - - Vector3 entry = Geometry::get_closest_point_to_segment(p->entry, edge); - float distance = p->entry.distance_to(entry) + p->distance; -#else - float distance = p->center.distance_to(e.C->center) + p->distance; -#endif - - if (e.C->prev_edge != -1) { - //oh this was visited already, can we win the cost? - - if (e.C->distance > distance) { - - e.C->prev_edge = e.C_edge; - e.C->distance = distance; -#ifdef USE_ENTRY_POINT - e.C->entry = entry; -#endif - } - } else { - //add to open neighbours - - e.C->prev_edge = e.C_edge; - e.C->distance = distance; -#ifdef USE_ENTRY_POINT - e.C->entry = entry; -#endif - open_list.push_back(e.C); - } - } - - open_list.erase(least_cost_poly); - } - - if (found_route) { - - Vector<Vector3> path; - - if (p_optimize) { - //string pulling - - Polygon *apex_poly = end_poly; - Vector3 apex_point = end_point; - Vector3 portal_left = apex_point; - Vector3 portal_right = apex_point; - Polygon *left_poly = end_poly; - Polygon *right_poly = end_poly; - Polygon *p = end_poly; - path.push_back(end_point); - - while (p) { - - Vector3 left; - Vector3 right; - -#define CLOCK_TANGENT(m_a, m_b, m_c) (((m_a) - (m_c)).cross((m_a) - (m_b))) - - if (p == begin_poly) { - left = begin_point; - right = begin_point; - } else { - int prev = p->prev_edge; - int prev_n = (p->prev_edge + 1) % p->edges.size(); - left = _get_vertex(p->edges[prev].point); - right = _get_vertex(p->edges[prev_n].point); - - //if (CLOCK_TANGENT(apex_point,left,(left+right)*0.5).dot(up) < 0){ - if (p->clockwise) { - SWAP(left, right); - } - } - - bool skip = false; - - if (CLOCK_TANGENT(apex_point, portal_left, left).dot(up) >= 0) { - //process - if (portal_left == apex_point || CLOCK_TANGENT(apex_point, left, portal_right).dot(up) > 0) { - left_poly = p; - portal_left = left; - } else { - - _clip_path(path, apex_poly, portal_right, right_poly); - - apex_point = portal_right; - p = right_poly; - left_poly = p; - apex_poly = p; - portal_left = apex_point; - portal_right = apex_point; - path.push_back(apex_point); - skip = true; - } - } - - if (!skip && CLOCK_TANGENT(apex_point, portal_right, right).dot(up) <= 0) { - //process - if (portal_right == apex_point || CLOCK_TANGENT(apex_point, right, portal_left).dot(up) < 0) { - right_poly = p; - portal_right = right; - } else { - - _clip_path(path, apex_poly, portal_left, left_poly); - - apex_point = portal_left; - p = left_poly; - right_poly = p; - apex_poly = p; - portal_right = apex_point; - portal_left = apex_point; - path.push_back(apex_point); - } - } - - if (p != begin_poly) - p = p->edges[p->prev_edge].C; - else - p = NULL; - } - - if (path[path.size() - 1] != begin_point) - path.push_back(begin_point); - - path.invert(); - - } else { - //midpoints - Polygon *p = end_poly; - - path.push_back(end_point); - while (true) { - int prev = p->prev_edge; -#ifdef USE_ENTRY_POINT - Vector3 point = p->entry; -#else - int prev_n = (p->prev_edge + 1) % p->edges.size(); - Vector3 point = (_get_vertex(p->edges[prev].point) + _get_vertex(p->edges[prev_n].point)) * 0.5; -#endif - path.push_back(point); - p = p->edges[prev].C; - if (p == begin_poly) - break; - } - - path.push_back(begin_point); - - path.invert(); - } - - return path; - } +Vector3 Navigation::get_up_vector() const { - return Vector<Vector3>(); + return up; } -Vector3 Navigation::get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, const bool &p_use_collision) { - - bool use_collision = p_use_collision; - Vector3 closest_point; - float closest_point_d = 1e20; - - for (Map<int, NavMesh>::Element *E = navmesh_map.front(); E; E = E->next()) { - - if (!E->get().linked) - continue; - for (List<Polygon>::Element *F = E->get().polygons.front(); F; F = F->next()) { - - Polygon &p = F->get(); - for (int i = 2; i < p.edges.size(); i++) { - - Face3 f(_get_vertex(p.edges[0].point), _get_vertex(p.edges[i - 1].point), _get_vertex(p.edges[i].point)); - Vector3 inters; - if (f.intersects_segment(p_from, p_to, &inters)) { - - if (!use_collision) { - closest_point = inters; - use_collision = true; - closest_point_d = p_from.distance_to(inters); - } else if (closest_point_d > inters.distance_to(p_from)) { - - closest_point = inters; - closest_point_d = p_from.distance_to(inters); - } - } - } - - if (!use_collision) { - - for (int i = 0; i < p.edges.size(); i++) { - - Vector3 a, b; - - Geometry::get_closest_points_between_segments(p_from, p_to, _get_vertex(p.edges[i].point), _get_vertex(p.edges[(i + 1) % p.edges.size()].point), a, b); - - float d = a.distance_to(b); - if (d < closest_point_d) { - - closest_point_d = d; - closest_point = b; - } - } - } - } - } - - return closest_point; +void Navigation::set_cell_size(float p_cell_size) { + cell_size = p_cell_size; + NavigationServer::get_singleton()->map_set_cell_size(map, cell_size); } -Vector3 Navigation::get_closest_point(const Vector3 &p_point) { - - Vector3 closest_point; - float closest_point_d = 1e20; - - for (Map<int, NavMesh>::Element *E = navmesh_map.front(); E; E = E->next()) { - - if (!E->get().linked) - continue; - for (List<Polygon>::Element *F = E->get().polygons.front(); F; F = F->next()) { - - Polygon &p = F->get(); - for (int i = 2; i < p.edges.size(); i++) { - - Face3 f(_get_vertex(p.edges[0].point), _get_vertex(p.edges[i - 1].point), _get_vertex(p.edges[i].point)); - Vector3 inters = f.get_closest_point_to(p_point); - float d = inters.distance_to(p_point); - if (d < closest_point_d) { - closest_point = inters; - closest_point_d = d; - } - } - } - } - - return closest_point; +void Navigation::set_edge_connection_margin(float p_edge_connection_margin) { + edge_connection_margin = p_edge_connection_margin; + NavigationServer::get_singleton()->map_set_edge_connection_margin(map, edge_connection_margin); } -Vector3 Navigation::get_closest_point_normal(const Vector3 &p_point) { +void Navigation::_bind_methods() { - Vector3 closest_point; - Vector3 closest_normal; - float closest_point_d = 1e20; + ClassDB::bind_method(D_METHOD("get_rid"), &Navigation::get_rid); - for (Map<int, NavMesh>::Element *E = navmesh_map.front(); E; E = E->next()) { + ClassDB::bind_method(D_METHOD("get_simple_path", "start", "end", "optimize"), &Navigation::get_simple_path, DEFVAL(true)); - if (!E->get().linked) - continue; - for (List<Polygon>::Element *F = E->get().polygons.front(); F; F = F->next()) { + ClassDB::bind_method(D_METHOD("set_up_vector", "up"), &Navigation::set_up_vector); + ClassDB::bind_method(D_METHOD("get_up_vector"), &Navigation::get_up_vector); - Polygon &p = F->get(); - for (int i = 2; i < p.edges.size(); i++) { + ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &Navigation::set_cell_size); + ClassDB::bind_method(D_METHOD("get_cell_size"), &Navigation::get_cell_size); - Face3 f(_get_vertex(p.edges[0].point), _get_vertex(p.edges[i - 1].point), _get_vertex(p.edges[i].point)); - Vector3 inters = f.get_closest_point_to(p_point); - float d = inters.distance_to(p_point); - if (d < closest_point_d) { - closest_point = inters; - closest_point_d = d; - closest_normal = f.get_plane().normal; - } - } - } - } + ClassDB::bind_method(D_METHOD("set_edge_connection_margin", "margin"), &Navigation::set_edge_connection_margin); + ClassDB::bind_method(D_METHOD("get_edge_connection_margin"), &Navigation::get_edge_connection_margin); - return closest_normal; + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "up_vector"), "set_up_vector", "get_up_vector"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "cell_size"), "set_cell_size", "get_cell_size"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "edge_connection_margin"), "set_edge_connection_margin", "get_edge_connection_margin"); } -Object *Navigation::get_closest_point_owner(const Vector3 &p_point) { - - Vector3 closest_point; - Object *owner = NULL; - float closest_point_d = 1e20; - - for (Map<int, NavMesh>::Element *E = navmesh_map.front(); E; E = E->next()) { - - if (!E->get().linked) - continue; - for (List<Polygon>::Element *F = E->get().polygons.front(); F; F = F->next()) { +void Navigation::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_READY: { + NavigationServer::get_singleton()->map_set_active(map, true); + } break; + case NOTIFICATION_EXIT_TREE: { - Polygon &p = F->get(); - for (int i = 2; i < p.edges.size(); i++) { - - Face3 f(_get_vertex(p.edges[0].point), _get_vertex(p.edges[i - 1].point), _get_vertex(p.edges[i].point)); - Vector3 inters = f.get_closest_point_to(p_point); - float d = inters.distance_to(p_point); - if (d < closest_point_d) { - closest_point = inters; - closest_point_d = d; - owner = E->get().owner; - } - } - } + NavigationServer::get_singleton()->map_set_active(map, false); + } break; } - - return owner; -} - -void Navigation::set_up_vector(const Vector3 &p_up) { - - up = p_up; -} - -Vector3 Navigation::get_up_vector() const { - - return up; } -void Navigation::_bind_methods() { - - ClassDB::bind_method(D_METHOD("navmesh_add", "mesh", "xform", "owner"), &Navigation::navmesh_add, DEFVAL(Variant())); - ClassDB::bind_method(D_METHOD("navmesh_set_transform", "id", "xform"), &Navigation::navmesh_set_transform); - ClassDB::bind_method(D_METHOD("navmesh_remove", "id"), &Navigation::navmesh_remove); +Navigation::Navigation() { - ClassDB::bind_method(D_METHOD("get_simple_path", "start", "end", "optimize"), &Navigation::get_simple_path, DEFVAL(true)); - ClassDB::bind_method(D_METHOD("get_closest_point_to_segment", "start", "end", "use_collision"), &Navigation::get_closest_point_to_segment, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("get_closest_point", "to_point"), &Navigation::get_closest_point); - ClassDB::bind_method(D_METHOD("get_closest_point_normal", "to_point"), &Navigation::get_closest_point_normal); - ClassDB::bind_method(D_METHOD("get_closest_point_owner", "to_point"), &Navigation::get_closest_point_owner); + map = NavigationServer::get_singleton()->map_create(); - ClassDB::bind_method(D_METHOD("set_up_vector", "up"), &Navigation::set_up_vector); - ClassDB::bind_method(D_METHOD("get_up_vector"), &Navigation::get_up_vector); + set_cell_size(0.3); + set_edge_connection_margin(5.0); // Five meters, depends alot on the agents radius - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "up_vector"), "set_up_vector", "get_up_vector"); + up = Vector3(0, 1, 0); } -Navigation::Navigation() { - - ERR_FAIL_COND(sizeof(Point) != 8); - cell_size = 0.01; //one centimeter - last_id = 1; - up = Vector3(0, 1, 0); +Navigation::~Navigation() { + NavigationServer::get_singleton()->free(map); } diff --git a/scene/3d/navigation.h b/scene/3d/navigation.h index f920d1d7f6..68e041ad73 100644 --- a/scene/3d/navigation.h +++ b/scene/3d/navigation.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,154 +31,45 @@ #ifndef NAVIGATION_H #define NAVIGATION_H -#include "scene/3d/navigation_mesh.h" +#include "scene/3d/navigation_mesh_instance.h" #include "scene/3d/spatial.h" class Navigation : public Spatial { GDCLASS(Navigation, Spatial); - union Point { - - struct { - int64_t x : 21; - int64_t y : 22; - int64_t z : 21; - }; - - uint64_t key; - bool operator<(const Point &p_key) const { return key < p_key.key; } - }; - - struct EdgeKey { - - Point a; - Point b; - - bool operator<(const EdgeKey &p_key) const { - return (a.key == p_key.a.key) ? (b.key < p_key.b.key) : (a.key < p_key.a.key); - }; - - EdgeKey(const Point &p_a = Point(), const Point &p_b = Point()) : - a(p_a), - b(p_b) { - if (a.key > b.key) { - SWAP(a, b); - } - } - }; - - struct NavMesh; - struct Polygon; - - struct ConnectionPending { - - Polygon *polygon; - int edge; - }; - - struct Polygon { - - struct Edge { - Point point; - Polygon *C; //connection - int C_edge; - List<ConnectionPending>::Element *P; - Edge() { - C = NULL; - C_edge = -1; - P = NULL; - } - }; - - Vector<Edge> edges; - - Vector3 center; - Vector3 entry; - - float distance; - int prev_edge; - bool clockwise; - - NavMesh *owner; - }; - - struct Connection { - - Polygon *A; - int A_edge; - Polygon *B; - int B_edge; - - List<ConnectionPending> pending; - - Connection() { - A = NULL; - B = NULL; - A_edge = -1; - B_edge = -1; - } - }; - - Map<EdgeKey, Connection> connections; - - struct NavMesh { - - Object *owner; - Transform xform; - bool linked; - Ref<NavigationMesh> navmesh; - List<Polygon> polygons; - }; - - _FORCE_INLINE_ Point _get_point(const Vector3 &p_pos) const { - - int x = int(Math::floor(p_pos.x / cell_size)); - int y = int(Math::floor(p_pos.y / cell_size)); - int z = int(Math::floor(p_pos.z / cell_size)); - - Point p; - p.key = 0; - p.x = x; - p.y = y; - p.z = z; - return p; - } - - _FORCE_INLINE_ Vector3 _get_vertex(const Point &p_point) const { - - return Vector3(p_point.x, p_point.y, p_point.z) * cell_size; - } - - void _navmesh_link(int p_id); - void _navmesh_unlink(int p_id); - - float cell_size; - Map<int, NavMesh> navmesh_map; - int last_id; + RID map; Vector3 up; - void _clip_path(Vector<Vector3> &path, Polygon *from_poly, const Vector3 &p_to_point, Polygon *p_to_poly); + real_t cell_size; + real_t edge_connection_margin; protected: static void _bind_methods(); + void _notification(int p_what); public: + RID get_rid() const { + return map; + } + void set_up_vector(const Vector3 &p_up); Vector3 get_up_vector() const; - //API should be as dynamic as possible - int navmesh_add(const Ref<NavigationMesh> &p_mesh, const Transform &p_xform, Object *p_owner = NULL); - void navmesh_set_transform(int p_id, const Transform &p_xform); - void navmesh_remove(int p_id); + void set_cell_size(float p_cell_size); + float get_cell_size() const { + return cell_size; + } + + void set_edge_connection_margin(float p_edge_connection_margin); + float get_edge_connection_margin() const { + return edge_connection_margin; + } Vector<Vector3> get_simple_path(const Vector3 &p_start, const Vector3 &p_end, bool p_optimize = true); - Vector3 get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, const bool &p_use_collision = false); - Vector3 get_closest_point(const Vector3 &p_point); - Vector3 get_closest_point_normal(const Vector3 &p_point); - Object *get_closest_point_owner(const Vector3 &p_point); Navigation(); + ~Navigation(); }; #endif // NAVIGATION_H diff --git a/scene/3d/navigation_agent.cpp b/scene/3d/navigation_agent.cpp new file mode 100644 index 0000000000..d3f447bc24 --- /dev/null +++ b/scene/3d/navigation_agent.cpp @@ -0,0 +1,361 @@ +/*************************************************************************/ +/* navigation_agent.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "navigation_agent.h" + +#include "core/engine.h" +#include "scene/3d/navigation.h" +#include "servers/navigation_server.h" + +void NavigationAgent::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_target_desired_distance", "desired_distance"), &NavigationAgent::set_target_desired_distance); + ClassDB::bind_method(D_METHOD("get_target_desired_distance"), &NavigationAgent::get_target_desired_distance); + + ClassDB::bind_method(D_METHOD("set_radius", "radius"), &NavigationAgent::set_radius); + ClassDB::bind_method(D_METHOD("get_radius"), &NavigationAgent::get_radius); + + ClassDB::bind_method(D_METHOD("set_agent_height_offset", "agent_height_offset"), &NavigationAgent::set_agent_height_offset); + ClassDB::bind_method(D_METHOD("get_agent_height_offset"), &NavigationAgent::get_agent_height_offset); + + ClassDB::bind_method(D_METHOD("set_ignore_y", "ignore"), &NavigationAgent::set_ignore_y); + ClassDB::bind_method(D_METHOD("get_ignore_y"), &NavigationAgent::get_ignore_y); + + ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationAgent::set_navigation_node); + ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationAgent::get_navigation_node); + + ClassDB::bind_method(D_METHOD("set_neighbor_dist", "neighbor_dist"), &NavigationAgent::set_neighbor_dist); + ClassDB::bind_method(D_METHOD("get_neighbor_dist"), &NavigationAgent::get_neighbor_dist); + + ClassDB::bind_method(D_METHOD("set_max_neighbors", "max_neighbors"), &NavigationAgent::set_max_neighbors); + ClassDB::bind_method(D_METHOD("get_max_neighbors"), &NavigationAgent::get_max_neighbors); + + ClassDB::bind_method(D_METHOD("set_time_horizon", "time_horizon"), &NavigationAgent::set_time_horizon); + ClassDB::bind_method(D_METHOD("get_time_horizon"), &NavigationAgent::get_time_horizon); + + ClassDB::bind_method(D_METHOD("set_max_speed", "max_speed"), &NavigationAgent::set_max_speed); + ClassDB::bind_method(D_METHOD("get_max_speed"), &NavigationAgent::get_max_speed); + + ClassDB::bind_method(D_METHOD("set_path_max_distance", "max_speed"), &NavigationAgent::set_path_max_distance); + ClassDB::bind_method(D_METHOD("get_path_max_distance"), &NavigationAgent::get_path_max_distance); + + ClassDB::bind_method(D_METHOD("set_target_location", "location"), &NavigationAgent::set_target_location); + ClassDB::bind_method(D_METHOD("get_target_location"), &NavigationAgent::get_target_location); + ClassDB::bind_method(D_METHOD("get_next_location"), &NavigationAgent::get_next_location); + ClassDB::bind_method(D_METHOD("distance_to_target"), &NavigationAgent::distance_to_target); + ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &NavigationAgent::set_velocity); + ClassDB::bind_method(D_METHOD("get_nav_path"), &NavigationAgent::get_nav_path); + ClassDB::bind_method(D_METHOD("get_nav_path_index"), &NavigationAgent::get_nav_path_index); + ClassDB::bind_method(D_METHOD("is_target_reached"), &NavigationAgent::is_target_reached); + ClassDB::bind_method(D_METHOD("is_target_reachable"), &NavigationAgent::is_target_reachable); + ClassDB::bind_method(D_METHOD("is_navigation_finished"), &NavigationAgent::is_navigation_finished); + ClassDB::bind_method(D_METHOD("get_final_location"), &NavigationAgent::get_final_location); + + ClassDB::bind_method(D_METHOD("_avoidance_done", "new_velocity"), &NavigationAgent::_avoidance_done); + + ADD_PROPERTY(PropertyInfo(Variant::REAL, "target_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01"), "set_target_desired_distance", "get_target_desired_distance"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0.1,100,0.01"), "set_radius", "get_radius"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "agent_height_offset", PROPERTY_HINT_RANGE, "-100.0,100,0.01"), "set_agent_height_offset", "get_agent_height_offset"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "neighbor_dist", PROPERTY_HINT_RANGE, "0.1,10000,0.01"), "set_neighbor_dist", "get_neighbor_dist"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_neighbors", PROPERTY_HINT_RANGE, "1,10000,1"), "set_max_neighbors", "get_max_neighbors"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "time_horizon", PROPERTY_HINT_RANGE, "0.01,100,0.01"), "set_time_horizon", "get_time_horizon"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_speed", PROPERTY_HINT_RANGE, "0.1,10000,0.01"), "set_max_speed", "get_max_speed"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "path_max_distance", PROPERTY_HINT_RANGE, "0.01,100,0.1"), "set_path_max_distance", "get_path_max_distance"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_y"), "set_ignore_y", "get_ignore_y"); + + ADD_SIGNAL(MethodInfo("path_changed")); + ADD_SIGNAL(MethodInfo("target_reached")); + ADD_SIGNAL(MethodInfo("navigation_finished")); + ADD_SIGNAL(MethodInfo("velocity_computed", PropertyInfo(Variant::VECTOR3, "safe_velocity"))); +} + +void NavigationAgent::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_READY: { + + agent_parent = Object::cast_to<Spatial>(get_parent()); + + NavigationServer::get_singleton()->agent_set_callback(agent, this, "_avoidance_done"); + + // Search the navigation node and set it + { + Navigation *nav = NULL; + Node *p = get_parent(); + while (p != NULL) { + nav = Object::cast_to<Navigation>(p); + if (nav != NULL) + p = NULL; + else + p = p->get_parent(); + } + + set_navigation(nav); + } + + set_physics_process_internal(true); + } break; + case NOTIFICATION_EXIT_TREE: { + agent_parent = NULL; + set_navigation(NULL); + set_physics_process_internal(false); + } break; + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { + if (agent_parent) { + + NavigationServer::get_singleton()->agent_set_position(agent, agent_parent->get_global_transform().origin); + if (!target_reached) { + if (distance_to_target() < target_desired_distance) { + emit_signal("target_reached"); + target_reached = true; + } + } + } + } break; + } +} + +NavigationAgent::NavigationAgent() : + agent_parent(NULL), + navigation(NULL), + agent(RID()), + target_desired_distance(1.0), + navigation_height_offset(0.0), + path_max_distance(3.0), + velocity_submitted(false), + target_reached(false), + navigation_finished(true) { + agent = NavigationServer::get_singleton()->agent_create(); + set_neighbor_dist(50.0); + set_max_neighbors(10); + set_time_horizon(5.0); + set_radius(1.0); + set_max_speed(10.0); + set_ignore_y(true); +} + +NavigationAgent::~NavigationAgent() { + NavigationServer::get_singleton()->free(agent); + agent = RID(); // Pointless +} + +void NavigationAgent::set_navigation(Navigation *p_nav) { + if (navigation == p_nav) + return; // Pointless + + navigation = p_nav; + NavigationServer::get_singleton()->agent_set_map(agent, navigation == NULL ? RID() : navigation->get_rid()); +} + +void NavigationAgent::set_navigation_node(Node *p_nav) { + Navigation *nav = Object::cast_to<Navigation>(p_nav); + ERR_FAIL_COND(nav == NULL); + set_navigation(nav); +} + +Node *NavigationAgent::get_navigation_node() const { + return Object::cast_to<Node>(navigation); +} + +void NavigationAgent::set_target_desired_distance(real_t p_dd) { + target_desired_distance = p_dd; +} + +void NavigationAgent::set_radius(real_t p_radius) { + radius = p_radius; + NavigationServer::get_singleton()->agent_set_radius(agent, radius); +} + +void NavigationAgent::set_agent_height_offset(real_t p_hh) { + navigation_height_offset = p_hh; +} + +void NavigationAgent::set_ignore_y(bool p_ignore_y) { + ignore_y = p_ignore_y; + NavigationServer::get_singleton()->agent_set_ignore_y(agent, ignore_y); +} + +void NavigationAgent::set_neighbor_dist(real_t p_dist) { + neighbor_dist = p_dist; + NavigationServer::get_singleton()->agent_set_neighbor_dist(agent, neighbor_dist); +} + +void NavigationAgent::set_max_neighbors(int p_count) { + max_neighbors = p_count; + NavigationServer::get_singleton()->agent_set_max_neighbors(agent, max_neighbors); +} + +void NavigationAgent::set_time_horizon(real_t p_time) { + time_horizon = p_time; + NavigationServer::get_singleton()->agent_set_time_horizon(agent, time_horizon); +} + +void NavigationAgent::set_max_speed(real_t p_max_speed) { + max_speed = p_max_speed; + NavigationServer::get_singleton()->agent_set_max_speed(agent, max_speed); +} + +void NavigationAgent::set_path_max_distance(real_t p_pmd) { + path_max_distance = p_pmd; +} + +real_t NavigationAgent::get_path_max_distance() { + return path_max_distance; +} + +void NavigationAgent::set_target_location(Vector3 p_location) { + target_location = p_location; + navigation_path.clear(); + target_reached = false; + navigation_finished = false; +} + +Vector3 NavigationAgent::get_target_location() const { + return target_location; +} + +Vector3 NavigationAgent::get_next_location() { + update_navigation(); + if (navigation_path.size() == 0) { + ERR_FAIL_COND_V(agent_parent == NULL, Vector3()); + return agent_parent->get_global_transform().origin; + } else { + return navigation_path[nav_path_index] - Vector3(0, navigation_height_offset, 0); + } +} + +real_t NavigationAgent::distance_to_target() const { + ERR_FAIL_COND_V(agent_parent == NULL, 0.0); + return agent_parent->get_global_transform().origin.distance_to(target_location); +} + +bool NavigationAgent::is_target_reached() const { + return target_reached; +} + +bool NavigationAgent::is_target_reachable() { + return target_desired_distance >= get_final_location().distance_to(target_location); +} + +bool NavigationAgent::is_navigation_finished() { + update_navigation(); + return navigation_finished; +} + +Vector3 NavigationAgent::get_final_location() { + update_navigation(); + if (navigation_path.size() == 0) { + return Vector3(); + } + return navigation_path[navigation_path.size() - 1]; +} + +void NavigationAgent::set_velocity(Vector3 p_velocity) { + target_velocity = p_velocity; + NavigationServer::get_singleton()->agent_set_target_velocity(agent, target_velocity); + NavigationServer::get_singleton()->agent_set_velocity(agent, prev_safe_velocity); + velocity_submitted = true; +} + +void NavigationAgent::_avoidance_done(Vector3 p_new_velocity) { + prev_safe_velocity = p_new_velocity; + + if (!velocity_submitted) { + target_velocity = Vector3(); + return; + } + velocity_submitted = false; + + emit_signal("velocity_computed", p_new_velocity); +} + +String NavigationAgent::get_configuration_warning() const { + if (!Object::cast_to<Spatial>(get_parent())) { + return TTR("The NavigationAgent can be used only under a spatial node."); + } + + return String(); +} + +void NavigationAgent::update_navigation() { + + if (agent_parent == NULL) return; + if (navigation == NULL) return; + if (update_frame_id == Engine::get_singleton()->get_physics_frames()) return; + + update_frame_id = Engine::get_singleton()->get_physics_frames(); + + Vector3 o = agent_parent->get_global_transform().origin; + + bool reload_path = false; + + if (NavigationServer::get_singleton()->agent_is_map_changed(agent)) { + reload_path = true; + } else if (navigation_path.size() == 0) { + reload_path = true; + } else { + // Check if too far from the navigation path + if (nav_path_index > 0) { + Vector3 segment[2]; + segment[0] = navigation_path[nav_path_index - 1]; + segment[1] = navigation_path[nav_path_index]; + segment[0].y -= navigation_height_offset; + segment[1].y -= navigation_height_offset; + Vector3 p = Geometry::get_closest_point_to_segment(o, segment); + if (o.distance_to(p) >= path_max_distance) { + // To faraway, reload path + reload_path = true; + } + } + } + + if (reload_path) { + navigation_path = NavigationServer::get_singleton()->map_get_path(navigation->get_rid(), o, target_location, true); + navigation_finished = false; + nav_path_index = 0; + emit_signal("path_changed"); + } + + if (navigation_path.size() == 0) + return; + + // Check if we can advance the navigation path + if (navigation_finished == false) { + // Advances to the next far away location. + while (o.distance_to(navigation_path[nav_path_index] - Vector3(0, navigation_height_offset, 0)) < target_desired_distance) { + nav_path_index += 1; + if (nav_path_index == navigation_path.size()) { + nav_path_index -= 1; + navigation_finished = true; + emit_signal("navigation_finished"); + break; + } + } + } +} diff --git a/scene/3d/navigation_agent.h b/scene/3d/navigation_agent.h new file mode 100644 index 0000000000..8f181dafe1 --- /dev/null +++ b/scene/3d/navigation_agent.h @@ -0,0 +1,162 @@ +/*************************************************************************/ +/* navigation_agent.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef NAVIGATION_AGENT_H +#define NAVIGATION_AGENT_H + +#include "core/vector.h" +#include "scene/main/node.h" + +class Spatial; +class Navigation; + +class NavigationAgent : public Node { + GDCLASS(NavigationAgent, Node); + + Spatial *agent_parent; + Navigation *navigation; + + RID agent; + + real_t target_desired_distance; + real_t radius; + real_t navigation_height_offset; + bool ignore_y; + real_t neighbor_dist; + int max_neighbors; + real_t time_horizon; + real_t max_speed; + + real_t path_max_distance; + + Vector3 target_location; + Vector<Vector3> navigation_path; + int nav_path_index; + bool velocity_submitted; + Vector3 prev_safe_velocity; + /// The submitted target velocity + Vector3 target_velocity; + bool target_reached; + bool navigation_finished; + // No initialized on purpose + uint32_t update_frame_id; + +protected: + static void _bind_methods(); + void _notification(int p_what); + +public: + NavigationAgent(); + virtual ~NavigationAgent(); + + void set_navigation(Navigation *p_nav); + const Navigation *get_navigation() const { + return navigation; + } + + void set_navigation_node(Node *p_nav); + Node *get_navigation_node() const; + + RID get_rid() const { + return agent; + } + + void set_target_desired_distance(real_t p_dd); + real_t get_target_desired_distance() const { + return target_desired_distance; + } + + void set_radius(real_t p_radius); + real_t get_radius() const { + return radius; + } + + void set_agent_height_offset(real_t p_hh); + real_t get_agent_height_offset() const { + return navigation_height_offset; + } + + void set_ignore_y(bool p_ignore_y); + bool get_ignore_y() const { + return ignore_y; + } + + void set_neighbor_dist(real_t p_dist); + real_t get_neighbor_dist() const { + return neighbor_dist; + } + + void set_max_neighbors(int p_count); + int get_max_neighbors() const { + return max_neighbors; + } + + void set_time_horizon(real_t p_time); + real_t get_time_horizon() const { + return time_horizon; + } + + void set_max_speed(real_t p_max_speed); + real_t get_max_speed() const { + return max_speed; + } + + void set_path_max_distance(real_t p_pmd); + real_t get_path_max_distance(); + + void set_target_location(Vector3 p_location); + Vector3 get_target_location() const; + + Vector3 get_next_location(); + + Vector<Vector3> get_nav_path() const { + return navigation_path; + } + + int get_nav_path_index() const { + return nav_path_index; + } + + real_t distance_to_target() const; + bool is_target_reached() const; + bool is_target_reachable(); + bool is_navigation_finished(); + Vector3 get_final_location(); + + void set_velocity(Vector3 p_velocity); + void _avoidance_done(Vector3 p_new_velocity); + + virtual String get_configuration_warning() const; + +private: + void update_navigation(); +}; + +#endif diff --git a/scene/3d/navigation_mesh_instance.cpp b/scene/3d/navigation_mesh_instance.cpp new file mode 100644 index 0000000000..ef59767078 --- /dev/null +++ b/scene/3d/navigation_mesh_instance.cpp @@ -0,0 +1,258 @@ +/*************************************************************************/ +/* navigation_mesh.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "navigation_mesh_instance.h" +#include "core/os/thread.h" +#include "mesh_instance.h" +#include "navigation.h" +#include "servers/navigation_server.h" + +void NavigationMeshInstance::set_enabled(bool p_enabled) { + + if (enabled == p_enabled) + return; + enabled = p_enabled; + + if (!is_inside_tree()) + return; + + if (!enabled) { + + NavigationServer::get_singleton()->region_set_map(region, RID()); + } else { + + if (navigation) { + + NavigationServer::get_singleton()->region_set_map(region, navigation->get_rid()); + } + } + + if (debug_view) { + MeshInstance *dm = Object::cast_to<MeshInstance>(debug_view); + if (is_enabled()) { + dm->set_material_override(get_tree()->get_debug_navigation_material()); + } else { + dm->set_material_override(get_tree()->get_debug_navigation_disabled_material()); + } + } + + update_gizmo(); +} + +bool NavigationMeshInstance::is_enabled() const { + + return enabled; +} + +///////////////////////////// + +void NavigationMeshInstance::_notification(int p_what) { + + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + + Spatial *c = this; + while (c) { + + navigation = Object::cast_to<Navigation>(c); + if (navigation) { + + if (enabled) { + + NavigationServer::get_singleton()->region_set_map(region, navigation->get_rid()); + } + break; + } + + c = c->get_parent_spatial(); + } + + if (navmesh.is_valid() && get_tree()->is_debugging_navigation_hint()) { + + MeshInstance *dm = memnew(MeshInstance); + dm->set_mesh(navmesh->get_debug_mesh()); + if (is_enabled()) { + dm->set_material_override(get_tree()->get_debug_navigation_material()); + } else { + dm->set_material_override(get_tree()->get_debug_navigation_disabled_material()); + } + add_child(dm); + debug_view = dm; + } + + } break; + case NOTIFICATION_TRANSFORM_CHANGED: { + + NavigationServer::get_singleton()->region_set_transform(region, get_global_transform()); + + } break; + case NOTIFICATION_EXIT_TREE: { + + if (navigation) { + + NavigationServer::get_singleton()->region_set_map(region, RID()); + } + + if (debug_view) { + debug_view->queue_delete(); + debug_view = NULL; + } + navigation = NULL; + } break; + } +} + +void NavigationMeshInstance::set_navigation_mesh(const Ref<NavigationMesh> &p_navmesh) { + + if (p_navmesh == navmesh) + return; + + if (navmesh.is_valid()) { + navmesh->remove_change_receptor(this); + } + + navmesh = p_navmesh; + + if (navmesh.is_valid()) { + navmesh->add_change_receptor(this); + } + + NavigationServer::get_singleton()->region_set_navmesh(region, p_navmesh); + + if (debug_view && navmesh.is_valid()) { + Object::cast_to<MeshInstance>(debug_view)->set_mesh(navmesh->get_debug_mesh()); + } + + emit_signal("navigation_mesh_changed"); + + update_gizmo(); + update_configuration_warning(); +} + +Ref<NavigationMesh> NavigationMeshInstance::get_navigation_mesh() const { + + return navmesh; +} + +struct BakeThreadsArgs { + NavigationMeshInstance *nav_mesh_instance; +}; + +void _bake_navigation_mesh(void *p_user_data) { + BakeThreadsArgs *args = static_cast<BakeThreadsArgs *>(p_user_data); + + if (args->nav_mesh_instance->get_navigation_mesh().is_valid()) { + Ref<NavigationMesh> nav_mesh = args->nav_mesh_instance->get_navigation_mesh()->duplicate(); + + NavigationServer::get_singleton()->region_bake_navmesh(nav_mesh, args->nav_mesh_instance); + args->nav_mesh_instance->call_deferred("_bake_finished", nav_mesh); + memdelete(args); + } else { + + ERR_PRINT("Can't bake the navigation mesh if the `NavigationMesh` resource doesn't exist"); + args->nav_mesh_instance->call_deferred("_bake_finished", Ref<NavigationMesh>()); + memdelete(args); + } +} + +void NavigationMeshInstance::bake_navigation_mesh() { + ERR_FAIL_COND(bake_thread != NULL); + + BakeThreadsArgs *args = memnew(BakeThreadsArgs); + args->nav_mesh_instance = this; + + bake_thread = Thread::create(_bake_navigation_mesh, args); + ERR_FAIL_COND(bake_thread == NULL); +} + +void NavigationMeshInstance::_bake_finished(Ref<NavigationMesh> p_nav_mesh) { + set_navigation_mesh(p_nav_mesh); + bake_thread = NULL; +} + +String NavigationMeshInstance::get_configuration_warning() const { + + if (!is_visible_in_tree() || !is_inside_tree()) + return String(); + + if (!navmesh.is_valid()) { + return TTR("A NavigationMesh resource must be set or created for this node to work."); + } + const Spatial *c = this; + while (c) { + + if (Object::cast_to<Navigation>(c)) + return String(); + + c = Object::cast_to<Spatial>(c->get_parent()); + } + + return TTR("NavigationMeshInstance must be a child or grandchild to a Navigation node. It only provides navigation data."); +} + +void NavigationMeshInstance::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_navigation_mesh", "navmesh"), &NavigationMeshInstance::set_navigation_mesh); + ClassDB::bind_method(D_METHOD("get_navigation_mesh"), &NavigationMeshInstance::get_navigation_mesh); + + ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationMeshInstance::set_enabled); + ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationMeshInstance::is_enabled); + + ClassDB::bind_method(D_METHOD("bake_navigation_mesh"), &NavigationMeshInstance::bake_navigation_mesh); + ClassDB::bind_method(D_METHOD("_bake_finished", "nav_mesh"), &NavigationMeshInstance::_bake_finished); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navmesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"), "set_navigation_mesh", "get_navigation_mesh"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled"); + + ADD_SIGNAL(MethodInfo("navigation_mesh_changed")); + ADD_SIGNAL(MethodInfo("bake_finished")); +} + +void NavigationMeshInstance::_changed_callback(Object *p_changed, const char *p_prop) { + update_gizmo(); + update_configuration_warning(); +} + +NavigationMeshInstance::NavigationMeshInstance() { + + enabled = true; + set_notify_transform(true); + region = NavigationServer::get_singleton()->region_create(); + + navigation = NULL; + debug_view = NULL; + bake_thread = NULL; +} + +NavigationMeshInstance::~NavigationMeshInstance() { + if (navmesh.is_valid()) + navmesh->remove_change_receptor(this); + NavigationServer::get_singleton()->free(region); +} diff --git a/scene/3d/room_instance.h b/scene/3d/navigation_mesh_instance.h index 01efde53c9..0f23c55cc7 100644 --- a/scene/3d/room_instance.h +++ b/scene/3d/navigation_mesh_instance.h @@ -1,12 +1,12 @@ /*************************************************************************/ -/* room_instance.h */ +/* navigation_mesh.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -28,54 +28,48 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef ROOM_INSTANCE_H -#define ROOM_INSTANCE_H +#ifndef NAVIGATION_MESH_INSTANCE_H +#define NAVIGATION_MESH_INSTANCE_H -#include "scene/3d/visual_instance.h" -#include "scene/resources/room.h" +#include "scene/3d/spatial.h" +#include "scene/resources/mesh.h" +#include "scene/resources/navigation_mesh.h" -/* RoomInstance Logic: - a) Instances that belong to the room are drawn only if the room is visible (seen through portal, or player inside) - b) Instances that don't belong to any room are considered to belong to the root room (RID empty) - c) "dynamic" Instances are assigned to the rooms their AABB touch +class Navigation; -*/ +class NavigationMeshInstance : public Spatial { -// FIXME: this will be removed, left for reference -#if 0 + GDCLASS(NavigationMeshInstance, Spatial); -class Room : public VisualInstance { + bool enabled; + RID region; + Ref<NavigationMesh> navmesh; - GDCLASS(Room, VisualInstance); - -public: -private: - Ref<RoomBounds> room; - - int level; - void _parse_node_faces(PoolVector<Face3> &all_faces, const Node *p_node) const; - - void _bounds_changed(); + Navigation *navigation; + Node *debug_view; + Thread *bake_thread; protected: void _notification(int p_what); - static void _bind_methods(); + void _changed_callback(Object *p_changed, const char *p_prop); public: - enum { - // used to notify portals that the room in which they are has changed. - NOTIFICATION_AREA_CHANGED = 60 - }; + void set_enabled(bool p_enabled); + bool is_enabled() const; + + void set_navigation_mesh(const Ref<NavigationMesh> &p_navmesh); + Ref<NavigationMesh> get_navigation_mesh() const; - virtual AABB get_aabb() const; - virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const; + /// Bakes the navigation mesh in a dedicated thread; once done, automatically + /// sets the new navigation mesh and emits a signal + void bake_navigation_mesh(); + void _bake_finished(Ref<NavigationMesh> p_nav_mesh); - void set_room(const Ref<RoomBounds> &p_room); - Ref<RoomBounds> get_room() const; + String get_configuration_warning() const; - Room(); - ~Room(); + NavigationMeshInstance(); + ~NavigationMeshInstance(); }; -#endif -#endif // ROOM_INSTANCE_H + +#endif // NAVIGATION_MESH_INSTANCE_H diff --git a/scene/3d/navigation_obstacle.cpp b/scene/3d/navigation_obstacle.cpp new file mode 100644 index 0000000000..74142bbb68 --- /dev/null +++ b/scene/3d/navigation_obstacle.cpp @@ -0,0 +1,163 @@ +/*************************************************************************/ +/* navigation_obstacle.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "navigation_obstacle.h" + +#include "scene/3d/collision_shape.h" +#include "scene/3d/navigation.h" +#include "scene/3d/physics_body.h" +#include "servers/navigation_server.h" + +void NavigationObstacle::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationObstacle::set_navigation_node); + ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationObstacle::get_navigation_node); +} + +void NavigationObstacle::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_READY: { + + update_agent_shape(); + + // Search the navigation node and set it + { + Navigation *nav = NULL; + Node *p = get_parent(); + while (p != NULL) { + nav = Object::cast_to<Navigation>(p); + if (nav != NULL) + p = NULL; + else + p = p->get_parent(); + } + + set_navigation(nav); + } + + set_physics_process_internal(true); + } break; + case NOTIFICATION_EXIT_TREE: { + set_navigation(NULL); + set_physics_process_internal(false); + } break; + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { + Spatial *spatial = Object::cast_to<Spatial>(get_parent()); + if (spatial) { + NavigationServer::get_singleton()->agent_set_position(agent, spatial->get_global_transform().origin); + } + + PhysicsBody *rigid = Object::cast_to<PhysicsBody>(get_parent()); + if (rigid) { + + Vector3 v = rigid->get_linear_velocity(); + NavigationServer::get_singleton()->agent_set_velocity(agent, v); + NavigationServer::get_singleton()->agent_set_target_velocity(agent, v); + } + + } break; + } +} + +NavigationObstacle::NavigationObstacle() : + navigation(NULL), + agent(RID()) { + agent = NavigationServer::get_singleton()->agent_create(); +} + +NavigationObstacle::~NavigationObstacle() { + NavigationServer::get_singleton()->free(agent); + agent = RID(); // Pointless +} + +void NavigationObstacle::set_navigation(Navigation *p_nav) { + if (navigation == p_nav) + return; // Pointless + + navigation = p_nav; + NavigationServer::get_singleton()->agent_set_map(agent, navigation == NULL ? RID() : navigation->get_rid()); +} + +void NavigationObstacle::set_navigation_node(Node *p_nav) { + Navigation *nav = Object::cast_to<Navigation>(p_nav); + ERR_FAIL_COND(nav == NULL); + set_navigation(nav); +} + +Node *NavigationObstacle::get_navigation_node() const { + return Object::cast_to<Node>(navigation); +} + +String NavigationObstacle::get_configuration_warning() const { + if (!Object::cast_to<Spatial>(get_parent())) { + + return TTR("The NavigationObstacle only serves to provide collision avoidance to a spatial object."); + } + + return String(); +} + +void NavigationObstacle::update_agent_shape() { + Node *node = get_parent(); + + // Estimate the radius of this physics body + real_t radius = 0.0; + for (int i(0); i < node->get_child_count(); i++) { + // For each collision shape + CollisionShape *cs = Object::cast_to<CollisionShape>(node->get_child(i)); + if (cs) { + // Take the distance between the Body center to the shape center + real_t r = cs->get_transform().origin.length(); + if (cs->get_shape().is_valid()) { + // and add the enclosing shape radius + r += cs->get_shape()->get_enclosing_radius(); + } + Vector3 s = cs->get_global_transform().basis.get_scale(); + r *= MAX(s.x, MAX(s.y, s.z)); + // Takes the biggest radius + radius = MAX(radius, r); + } + } + Spatial *spa = Object::cast_to<Spatial>(node); + if (spa) { + Vector3 s = spa->get_global_transform().basis.get_scale(); + radius *= MAX(s.x, MAX(s.y, s.z)); + } + + if (radius == 0.0) + radius = 1.0; // Never a 0 radius + + // Initialize the Agent as an object + NavigationServer::get_singleton()->agent_set_neighbor_dist(agent, 0.0); + NavigationServer::get_singleton()->agent_set_max_neighbors(agent, 0); + NavigationServer::get_singleton()->agent_set_time_horizon(agent, 0.0); + NavigationServer::get_singleton()->agent_set_radius(agent, radius); + NavigationServer::get_singleton()->agent_set_max_speed(agent, 0.0); +} diff --git a/scene/resources/room.h b/scene/3d/navigation_obstacle.h index 2c53ea1aed..34f8153614 100644 --- a/scene/resources/room.h +++ b/scene/3d/navigation_obstacle.h @@ -1,12 +1,12 @@ /*************************************************************************/ -/* room.h */ +/* navigation_obstacle.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -28,35 +28,44 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef ROOM_BOUNDS_H -#define ROOM_BOUNDS_H +#ifndef NAVIGATION_OBSTACLE_H +#define NAVIGATION_OBSTACLE_H -#include "core/math/bsp_tree.h" -#include "core/resource.h" +#include "scene/main/node.h" -// FIXME: left for reference but will be removed when portals are reimplemented using Area -#if 0 +class Navigation; -class RoomBounds : public Resource { +class NavigationObstacle : public Node { + GDCLASS(NavigationObstacle, Node); - GDCLASS(RoomBounds, Resource); - RES_BASE_EXTENSION("room"); + Navigation *navigation; - RID area; - PoolVector<Face3> geometry_hint; + RID agent; protected: static void _bind_methods(); + void _notification(int p_what); public: - virtual RID get_rid() const; + NavigationObstacle(); + virtual ~NavigationObstacle(); - void set_geometry_hint(const PoolVector<Face3> &p_geometry_hint); - PoolVector<Face3> get_geometry_hint() const; + void set_navigation(Navigation *p_nav); + const Navigation *get_navigation() const { + return navigation; + } - RoomBounds(); - ~RoomBounds(); + void set_navigation_node(Node *p_nav); + Node *get_navigation_node() const; + + RID get_rid() const { + return agent; + } + + virtual String get_configuration_warning() const; + +private: + void update_agent_shape(); }; #endif -#endif // ROOM_H diff --git a/scene/3d/particles.cpp b/scene/3d/particles.cpp index 06b5613eb8..add563d991 100644 --- a/scene/3d/particles.cpp +++ b/scene/3d/particles.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/particles.h b/scene/3d/particles.h index 391491e8b8..69be7da29a 100644 --- a/scene/3d/particles.h +++ b/scene/3d/particles.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/path.cpp b/scene/3d/path.cpp index d55c795d38..ac012de1ab 100644 --- a/scene/3d/path.cpp +++ b/scene/3d/path.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -111,18 +111,15 @@ void PathFollow::_update_transform() { return; } float bi = c->get_bake_interval(); - float o = offset; float o_next = offset + bi; if (loop) { - o = Math::fposmod(o, bl); o_next = Math::fposmod(o_next, bl); } else if (rotation_mode == ROTATION_ORIENTED && o_next >= bl) { - o = bl - bi; o_next = bl; } - Vector3 pos = c->interpolate_baked(o, cubic); + Vector3 pos = c->interpolate_baked(offset, cubic); Transform t = get_transform(); // Vector3 pos_offset = Vector3(h_offset, v_offset, 0); not used in all cases // will be replaced by "Vector3(h_offset, v_offset, 0)" where it was formerly used @@ -136,9 +133,9 @@ void PathFollow::_update_transform() { else forward.normalize(); - Vector3 up = c->interpolate_baked_up_vector(o, true); + Vector3 up = c->interpolate_baked_up_vector(offset, true); - if (o_next < o) { + if (o_next < offset) { Vector3 up1 = c->interpolate_baked_up_vector(o_next, true); Vector3 axis = up.cross(up1); @@ -166,8 +163,8 @@ void PathFollow::_update_transform() { t.origin = pos; - Vector3 t_prev = (pos - c->interpolate_baked(o - delta_offset, cubic)).normalized(); - Vector3 t_cur = (c->interpolate_baked(o + delta_offset, cubic) - pos).normalized(); + Vector3 t_prev = (pos - c->interpolate_baked(offset - delta_offset, cubic)).normalized(); + Vector3 t_cur = (c->interpolate_baked(offset + delta_offset, cubic) - pos).normalized(); Vector3 axis = t_prev.cross(t_cur); float dot = t_prev.dot(t_cur); @@ -190,7 +187,7 @@ void PathFollow::_update_transform() { } // do the additional tilting - float tilt_angle = c->interpolate_baked_tilt(o); + float tilt_angle = c->interpolate_baked_tilt(offset); Vector3 tilt_axis = t_cur; // not sure what tilt is supposed to do, is this correct?? if (likely(!Math::is_zero_approx(Math::abs(tilt_angle)))) { @@ -256,7 +253,7 @@ void PathFollow::_validate_property(PropertyInfo &property) const { if (path && path->get_curve().is_valid()) max = path->get_curve()->get_baked_length(); - property.hint_string = "0," + rtos(max) + ",0.01,or_greater"; + property.hint_string = "0," + rtos(max) + ",0.01,or_lesser,or_greater"; } } @@ -300,8 +297,8 @@ void PathFollow::_bind_methods() { ClassDB::bind_method(D_METHOD("set_loop", "loop"), &PathFollow::set_loop); ClassDB::bind_method(D_METHOD("has_loop"), &PathFollow::has_loop); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "offset", PROPERTY_HINT_RANGE, "0,10000,0.01,or_greater"), "set_offset", "get_offset"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_offset", PROPERTY_HINT_RANGE, "0,1,0.0001,or_greater", PROPERTY_USAGE_EDITOR), "set_unit_offset", "get_unit_offset"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "offset", PROPERTY_HINT_RANGE, "0,10000,0.01,or_lesser,or_greater"), "set_offset", "get_offset"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_offset", PROPERTY_HINT_RANGE, "0,1,0.0001,or_lesser,or_greater", PROPERTY_USAGE_EDITOR), "set_unit_offset", "get_unit_offset"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "h_offset"), "set_h_offset", "get_h_offset"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "v_offset"), "set_v_offset", "get_v_offset"); ADD_PROPERTY(PropertyInfo(Variant::INT, "rotation_mode", PROPERTY_HINT_ENUM, "None,Y,XY,XYZ,Oriented"), "set_rotation_mode", "get_rotation_mode"); @@ -319,8 +316,24 @@ void PathFollow::set_offset(float p_offset) { delta_offset = p_offset - offset; offset = p_offset; - if (path) + if (path) { + if (path->get_curve().is_valid() && path->get_curve()->get_baked_length()) { + float path_length = path->get_curve()->get_baked_length(); + + if (loop) { + while (offset > path_length) + offset -= path_length; + + while (offset < 0) + offset += path_length; + + } else { + offset = CLAMP(offset, 0, path_length); + } + } + _update_transform(); + } _change_notify("offset"); _change_notify("unit_offset"); } diff --git a/scene/3d/path.h b/scene/3d/path.h index 2a12c4a826..497913b925 100644 --- a/scene/3d/path.h +++ b/scene/3d/path.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index a107c3bf7a..fbfd372272 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -36,15 +36,14 @@ #include "core/method_bind_ext.gen.inc" #include "core/object.h" #include "core/rid.h" +#include "scene/3d/collision_shape.h" #include "scene/scene_string_names.h" +#include "servers/navigation_server.h" #ifdef TOOLS_ENABLED #include "editor/plugins/spatial_editor_plugin.h" #endif -void PhysicsBody::_notification(int p_what) { -} - Vector3 PhysicsBody::get_linear_velocity() const { return Vector3(); @@ -1014,7 +1013,7 @@ void RigidBody::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "gravity_scale", PROPERTY_HINT_RANGE, "-128,128,0.01"), "set_gravity_scale", "get_gravity_scale"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "continuous_cd"), "set_use_continuous_collision_detection", "is_using_continuous_collision_detection"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "contacts_reported"), "set_max_contacts_reported", "get_max_contacts_reported"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "contacts_reported", PROPERTY_HINT_RANGE, "0,64,1,or_greater"), "set_max_contacts_reported", "get_max_contacts_reported"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "contact_monitor"), "set_contact_monitor", "is_contact_monitor_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleeping", "is_sleeping"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_sleep"), "set_can_sleep", "is_able_to_sleep"); @@ -1104,6 +1103,14 @@ Ref<KinematicCollision> KinematicBody::_move(const Vector3 &p_motion, bool p_inf return Ref<KinematicCollision>(); } +Vector3 KinematicBody::get_linear_velocity() const { + return linear_velocity; +} + +Vector3 KinematicBody::get_angular_velocity() const { + return angular_velocity; +} + bool KinematicBody::move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes, bool p_test_only) { Transform gt = get_global_transform(); @@ -1140,27 +1147,28 @@ bool KinematicBody::move_and_collide(const Vector3 &p_motion, bool p_infinite_in //so, if you pass 45 as limit, avoid numerical precision errors when angle is 45. #define FLOOR_ANGLE_THRESHOLD 0.01 -Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { +Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { - Vector3 lv = p_linear_velocity; + Vector3 body_velocity = p_linear_velocity; + Vector3 body_velocity_normal = body_velocity.normalized(); for (int i = 0; i < 3; i++) { if (locked_axis & (1 << i)) { - lv[i] = 0; + body_velocity[i] = 0; } } // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky - Vector3 motion = (floor_velocity + lv) * (Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time()); + Vector3 motion = (floor_velocity + body_velocity) * (Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time()); on_floor = false; + on_floor_body = RID(); on_ceiling = false; on_wall = false; colliders.clear(); + floor_normal = Vector3(); floor_velocity = Vector3(); - Vector3 lv_n = p_linear_velocity.normalized(); - while (p_max_slides) { Collision collision; @@ -1187,47 +1195,38 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve colliders.push_back(collision); motion = collision.remainder; - bool is_on_slope = false; - if (p_floor_direction == Vector3()) { + if (p_up_direction == Vector3()) { //all is a wall on_wall = true; } else { - if (Math::acos(collision.normal.dot(p_floor_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor + if (Math::acos(collision.normal.dot(p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor on_floor = true; + floor_normal = collision.normal; on_floor_body = collision.collider_rid; floor_velocity = collision.collider_vel; if (p_stop_on_slope) { - if ((lv_n + p_floor_direction).length() < 0.01 && collision.travel.length() < 1) { + if ((body_velocity_normal + p_up_direction).length() < 0.01 && collision.travel.length() < 1) { Transform gt = get_global_transform(); - gt.origin -= collision.travel.slide(p_floor_direction); + gt.origin -= collision.travel.slide(p_up_direction); set_global_transform(gt); return Vector3(); } } - - is_on_slope = true; - - } else if (Math::acos(collision.normal.dot(-p_floor_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling + } else if (Math::acos(collision.normal.dot(-p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling on_ceiling = true; } else { on_wall = true; } } - if (p_stop_on_slope && is_on_slope) { - motion = motion.slide(p_floor_direction); - lv = lv.slide(p_floor_direction); - } else { - Vector3 n = collision.normal; - motion = motion.slide(n); - lv = lv.slide(n); - } + motion = motion.slide(collision.normal); + body_velocity = body_velocity.slide(collision.normal); for (int j = 0; j < 3; j++) { if (locked_axis & (1 << j)) { - lv[j] = 0; + body_velocity[j] = 0; } } } @@ -1239,14 +1238,14 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve --p_max_slides; } - return lv; + return body_velocity; } -Vector3 KinematicBody::move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_floor_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { +Vector3 KinematicBody::move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { bool was_on_floor = on_floor; - Vector3 ret = move_and_slide(p_linear_velocity, p_floor_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia); + Vector3 ret = move_and_slide(p_linear_velocity, p_up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia); if (!was_on_floor || p_snap == Vector3()) { return ret; } @@ -1257,15 +1256,16 @@ Vector3 KinematicBody::move_and_slide_with_snap(const Vector3 &p_linear_velocity if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) { bool apply = true; - if (p_floor_direction != Vector3()) { - if (Math::acos(p_floor_direction.normalized().dot(col.normal)) < p_floor_max_angle) { + if (p_up_direction != Vector3()) { + if (Math::acos(p_up_direction.normalized().dot(col.normal)) < p_floor_max_angle) { on_floor = true; + floor_normal = col.normal; on_floor_body = col.collider_rid; floor_velocity = col.collider_vel; if (p_stop_on_slope) { // move and collide may stray the object a bit because of pre un-stucking, // so only ensure that motion happens on floor direction in this case. - col.travel = col.travel.project(p_floor_direction); + col.travel = col.travel.project(p_up_direction); } } else { apply = false; //snapped with floor direction, but did not snap to a floor, do not snap. @@ -1294,6 +1294,11 @@ bool KinematicBody::is_on_ceiling() const { return on_ceiling; } +Vector3 KinematicBody::get_floor_normal() const { + + return floor_normal; +} + Vector3 KinematicBody::get_floor_velocity() const { return floor_velocity; @@ -1401,15 +1406,18 @@ void KinematicBody::_notification(int p_what) { void KinematicBody::_bind_methods() { + ClassDB::bind_method(D_METHOD("_direct_state_changed"), &KinematicBody::_direct_state_changed); + ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "exclude_raycast_shapes", "test_only"), &KinematicBody::_move, DEFVAL(true), DEFVAL(true), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true)); - ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "floor_normal", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody::move_and_slide_with_snap, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody::move_and_slide_with_snap, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true)); ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia"), &KinematicBody::test_move, DEFVAL(true)); ClassDB::bind_method(D_METHOD("is_on_floor"), &KinematicBody::is_on_floor); ClassDB::bind_method(D_METHOD("is_on_ceiling"), &KinematicBody::is_on_ceiling); ClassDB::bind_method(D_METHOD("is_on_wall"), &KinematicBody::is_on_wall); + ClassDB::bind_method(D_METHOD("get_floor_normal"), &KinematicBody::get_floor_normal); ClassDB::bind_method(D_METHOD("get_floor_velocity"), &KinematicBody::get_floor_velocity); ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &KinematicBody::set_axis_lock); @@ -1428,6 +1436,17 @@ void KinematicBody::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin"); } +void KinematicBody::_direct_state_changed(Object *p_state) { +#ifdef DEBUG_ENABLED + PhysicsDirectBodyState *state = Object::cast_to<PhysicsDirectBodyState>(p_state); +#else + PhysicsDirectBodyState *state = (PhysicsDirectBodyState *)p_state; //trust it +#endif + + linear_velocity = state->get_linear_velocity(); + angular_velocity = state->get_angular_velocity(); +} + KinematicBody::KinematicBody() : PhysicsBody(PhysicsServer::BODY_MODE_KINEMATIC) { @@ -1436,6 +1455,8 @@ KinematicBody::KinematicBody() : on_floor = false; on_ceiling = false; on_wall = false; + + PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); } KinematicBody::~KinematicBody() { @@ -1555,6 +1576,32 @@ bool PhysicalBone::JointData::_get(const StringName &p_name, Variant &r_ret) con void PhysicalBone::JointData::_get_property_list(List<PropertyInfo> *p_list) const { } +void PhysicalBone::apply_central_impulse(const Vector3 &p_impulse) { + PhysicsServer::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse); +} + +void PhysicalBone::apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse) { + PhysicsServer::get_singleton()->body_apply_impulse(get_rid(), p_pos, p_impulse); +} + +void PhysicalBone::reset_physics_simulation_state() { + if (simulate_physics) { + _start_physics_simulation(); + } else { + _stop_physics_simulation(); + } +} + +void PhysicalBone::reset_to_rest_position() { + if (parent_skeleton) { + if (-1 == bone_id) { + set_global_transform(parent_skeleton->get_global_transform() * body_offset); + } else { + set_global_transform(parent_skeleton->get_global_transform() * parent_skeleton->get_bone_global_pose(bone_id) * body_offset); + } + } +} + bool PhysicalBone::PinJointData::_set(const StringName &p_name, const Variant &p_value, RID j) { if (JointData::_set(p_name, p_value, j)) { return true; @@ -2160,7 +2207,10 @@ void PhysicalBone::_notification(int p_what) { parent_skeleton = find_skeleton_parent(get_parent()); update_bone_id(); reset_to_rest_position(); - _reset_physics_simulation_state(); + reset_physics_simulation_state(); + if (!joint.is_valid() && joint_data) { + _reload_joint(); + } break; case NOTIFICATION_EXIT_TREE: if (parent_skeleton) { @@ -2169,7 +2219,10 @@ void PhysicalBone::_notification(int p_what) { } } parent_skeleton = NULL; - update_bone_id(); + if (joint.is_valid()) { + PhysicsServer::get_singleton()->free(joint); + joint = RID(); + } break; case NOTIFICATION_TRANSFORM_CHANGED: if (Engine::get_singleton()->is_editor_hint()) { @@ -2211,6 +2264,9 @@ void PhysicalBone::_direct_state_changed(Object *p_state) { } void PhysicalBone::_bind_methods() { + ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &PhysicalBone::apply_central_impulse); + ClassDB::bind_method(D_METHOD("apply_impulse", "position", "impulse"), &PhysicalBone::apply_impulse); + ClassDB::bind_method(D_METHOD("_direct_state_changed"), &PhysicalBone::_direct_state_changed); ClassDB::bind_method(D_METHOD("set_joint_type", "joint_type"), &PhysicalBone::set_joint_type); @@ -2222,8 +2278,6 @@ void PhysicalBone::_bind_methods() { ClassDB::bind_method(D_METHOD("set_body_offset", "offset"), &PhysicalBone::set_body_offset); ClassDB::bind_method(D_METHOD("get_body_offset"), &PhysicalBone::get_body_offset); - ClassDB::bind_method(D_METHOD("is_static_body"), &PhysicalBone::is_static_body); - ClassDB::bind_method(D_METHOD("get_simulate_physics"), &PhysicalBone::get_simulate_physics); ClassDB::bind_method(D_METHOD("is_simulating_physics"), &PhysicalBone::is_simulating_physics); @@ -2492,26 +2546,13 @@ const Transform &PhysicalBone::get_joint_offset() const { return joint_offset; } -void PhysicalBone::set_static_body(bool p_static) { - - static_body = p_static; - - set_as_toplevel(!static_body); - - _reset_physics_simulation_state(); -} - -bool PhysicalBone::is_static_body() { - return static_body; -} - void PhysicalBone::set_simulate_physics(bool p_simulate) { if (simulate_physics == p_simulate) { return; } simulate_physics = p_simulate; - _reset_physics_simulation_state(); + reset_physics_simulation_state(); } bool PhysicalBone::get_simulate_physics() { @@ -2519,7 +2560,7 @@ bool PhysicalBone::get_simulate_physics() { } bool PhysicalBone::is_simulating_physics() { - return _internal_simulate_physics && !_internal_static_body; + return _internal_simulate_physics; } void PhysicalBone::set_bone_name(const String &p_name) { @@ -2602,8 +2643,6 @@ PhysicalBone::PhysicalBone() : #endif joint_data(NULL), parent_skeleton(NULL), - static_body(false), - _internal_static_body(false), simulate_physics(false), _internal_simulate_physics(false), bone_id(-1), @@ -2613,8 +2652,7 @@ PhysicalBone::PhysicalBone() : friction(1), gravity_scale(1) { - set_static_body(static_body); - _reset_physics_simulation_state(); + reset_physics_simulation_state(); } PhysicalBone::~PhysicalBone() { @@ -2641,8 +2679,7 @@ void PhysicalBone::update_bone_id() { parent_skeleton->bind_physical_bone_to_bone(bone_id, this); _fix_joint_offset(); - _internal_static_body = !static_body; // Force staticness reset - _reset_staticness_state(); + reset_physics_simulation_state(); } } @@ -2664,49 +2701,6 @@ void PhysicalBone::update_offset() { #endif } -void PhysicalBone::reset_to_rest_position() { - if (parent_skeleton) { - if (-1 == bone_id) { - set_global_transform(parent_skeleton->get_global_transform() * body_offset); - } else { - set_global_transform(parent_skeleton->get_global_transform() * parent_skeleton->get_bone_global_pose(bone_id) * body_offset); - } - } -} - -void PhysicalBone::_reset_physics_simulation_state() { - if (simulate_physics && !static_body) { - _start_physics_simulation(); - } else { - _stop_physics_simulation(); - } - - _reset_staticness_state(); -} - -void PhysicalBone::_reset_staticness_state() { - - if (parent_skeleton && -1 != bone_id) { - if (static_body && simulate_physics) { // With this check I'm sure the position of this body is updated only when it's necessary - - if (_internal_static_body) { - return; - } - - parent_skeleton->bind_child_node_to_bone(bone_id, this); - _internal_static_body = true; - } else { - - if (!_internal_static_body) { - return; - } - - parent_skeleton->unbind_child_node_from_bone(bone_id, this); - _internal_static_body = false; - } - } -} - void PhysicalBone::_start_physics_simulation() { if (_internal_simulate_physics || !parent_skeleton) { return; @@ -2716,17 +2710,27 @@ void PhysicalBone::_start_physics_simulation() { PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer()); PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask()); PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); + set_as_toplevel(true); _internal_simulate_physics = true; } void PhysicalBone::_stop_physics_simulation() { - if (!_internal_simulate_physics || !parent_skeleton) { + if (!parent_skeleton) { return; } - PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_STATIC); - PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), 0); - PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), 0); - PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), NULL, ""); - parent_skeleton->set_bone_global_pose_override(bone_id, Transform(), 0.0, false); - _internal_simulate_physics = false; + if (parent_skeleton->get_animate_physical_bones()) { + PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_KINEMATIC); + PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer()); + PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask()); + } else { + PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_STATIC); + PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), 0); + PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), 0); + } + if (_internal_simulate_physics) { + PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), NULL, ""); + parent_skeleton->set_bone_global_pose_override(bone_id, Transform(), 0.0, false); + set_as_toplevel(false); + _internal_simulate_physics = false; + } } diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h index 0967cb9cd5..0ee877d887 100644 --- a/scene/3d/physics_body.h +++ b/scene/3d/physics_body.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -49,7 +49,6 @@ class PhysicsBody : public CollisionObject { protected: static void _bind_methods(); - void _notification(int p_what); PhysicsBody(PhysicsServer::BodyMode p_mode); public: @@ -296,10 +295,14 @@ public: }; private: + Vector3 linear_velocity; + Vector3 angular_velocity; + uint16_t locked_axis; float margin; + Vector3 floor_normal; Vector3 floor_velocity; RID on_floor_body; bool on_floor; @@ -318,7 +321,12 @@ protected: void _notification(int p_what); static void _bind_methods(); + virtual void _direct_state_changed(Object *p_state); + public: + virtual Vector3 get_linear_velocity() const; + virtual Vector3 get_angular_velocity() const; + bool move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes = true, bool p_test_only = false); bool test_move(const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia); @@ -330,11 +338,12 @@ public: void set_safe_margin(float p_margin); float get_safe_margin() const; - Vector3 move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction = Vector3(0, 0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); - Vector3 move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_floor_direction = Vector3(0, 0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); + Vector3 move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_up_direction = Vector3(0, 0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); + Vector3 move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_up_direction = Vector3(0, 0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); bool is_on_floor() const; bool is_on_wall() const; bool is_on_ceiling() const; + Vector3 get_floor_normal() const; Vector3 get_floor_velocity() const; int get_slide_count() const; @@ -560,8 +569,6 @@ private: Skeleton *parent_skeleton; Transform body_offset; Transform body_offset_inverse; - bool static_body; - bool _internal_static_body; bool simulate_physics; bool _internal_simulate_physics; int bone_id; @@ -611,9 +618,6 @@ public: void set_body_offset(const Transform &p_offset); const Transform &get_body_offset() const; - void set_static_body(bool p_static); - bool is_static_body(); - void set_simulate_physics(bool p_simulate); bool get_simulate_physics(); bool is_simulating_physics(); @@ -636,16 +640,18 @@ public: void set_gravity_scale(real_t p_gravity_scale); real_t get_gravity_scale() const; + void apply_central_impulse(const Vector3 &p_impulse); + void apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse); + + void reset_physics_simulation_state(); + void reset_to_rest_position(); + PhysicalBone(); ~PhysicalBone(); private: void update_bone_id(); void update_offset(); - void reset_to_rest_position(); - - void _reset_physics_simulation_state(); - void _reset_staticness_state(); void _start_physics_simulation(); void _stop_physics_simulation(); diff --git a/scene/3d/physics_joint.cpp b/scene/3d/physics_joint.cpp index c261ed3aeb..eacc6bcc0f 100644 --- a/scene/3d/physics_joint.cpp +++ b/scene/3d/physics_joint.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/physics_joint.h b/scene/3d/physics_joint.h index f6df920314..d03dbac392 100644 --- a/scene/3d/physics_joint.h +++ b/scene/3d/physics_joint.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/portal.cpp b/scene/3d/portal.cpp deleted file mode 100644 index f5163dfcdd..0000000000 --- a/scene/3d/portal.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/*************************************************************************/ -/* portal.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "portal.h" -#include "core/project_settings.h" -#include "scene/resources/surface_tool.h" -#include "servers/visual_server.h" - -// FIXME: This will be removed, kept as reference for new implementation -#if 0 -bool Portal::_set(const StringName &p_name, const Variant &p_value) { - - if (p_name == "shape") { - PoolVector<float> src_coords = p_value; - Vector<Point2> points; - int src_coords_size = src_coords.size(); - ERR_FAIL_COND_V(src_coords_size % 2, false); - points.resize(src_coords_size / 2); - for (int i = 0; i < points.size(); i++) { - - points[i].x = src_coords[i * 2 + 0]; - points[i].y = src_coords[i * 2 + 1]; - set_shape(points); - } - } else if (p_name == "enabled") { - set_enabled(p_value); - } else if (p_name == "disable_distance") { - set_disable_distance(p_value); - } else if (p_name == "disabled_color") { - set_disabled_color(p_value); - } else if (p_name == "connect_range") { - set_connect_range(p_value); - } else - return false; - - return true; -} - -bool Portal::_get(const StringName &p_name, Variant &r_ret) const { - - if (p_name == "shape") { - Vector<Point2> points = get_shape(); - PoolVector<float> dst_coords; - dst_coords.resize(points.size() * 2); - - for (int i = 0; i < points.size(); i++) { - - dst_coords.set(i * 2 + 0, points[i].x); - dst_coords.set(i * 2 + 1, points[i].y); - } - - r_ret = dst_coords; - } else if (p_name == "enabled") { - r_ret = is_enabled(); - } else if (p_name == "disable_distance") { - r_ret = get_disable_distance(); - } else if (p_name == "disabled_color") { - r_ret = get_disabled_color(); - } else if (p_name == "connect_range") { - r_ret = get_connect_range(); - } else - return false; - return true; -} - -void Portal::_get_property_list(List<PropertyInfo> *p_list) const { - - p_list->push_back(PropertyInfo(Variant::POOL_REAL_ARRAY, "shape")); - p_list->push_back(PropertyInfo(Variant::BOOL, "enabled")); - p_list->push_back(PropertyInfo(Variant::REAL, "disable_distance", PROPERTY_HINT_RANGE, "0,4096,0.01")); - p_list->push_back(PropertyInfo(Variant::COLOR, "disabled_color")); - p_list->push_back(PropertyInfo(Variant::REAL, "connect_range", PROPERTY_HINT_RANGE, "0.1,4096,0.01")); -} - -AABB Portal::get_aabb() const { - - return aabb; -} -PoolVector<Face3> Portal::get_faces(uint32_t p_usage_flags) const { - - if (!(p_usage_flags & FACES_ENCLOSING)) - return PoolVector<Face3>(); - - Vector<Point2> shape = get_shape(); - if (shape.size() == 0) - return PoolVector<Face3>(); - - Vector2 center; - for (int i = 0; i < shape.size(); i++) { - - center += shape[i]; - } - - PoolVector<Face3> ret; - center /= shape.size(); - - for (int i = 0; i < shape.size(); i++) { - - int n = (i + 1) % shape.size(); - - Face3 f; - f.vertex[0] = Vector3(center.x, center.y, 0); - f.vertex[1] = Vector3(shape[i].x, shape[i].y, 0); - f.vertex[2] = Vector3(shape[n].x, shape[n].y, 0); - ret.push_back(f); - } - - return ret; -} - -void Portal::set_shape(const Vector<Point2> &p_shape) { - - VisualServer::get_singleton()->portal_set_shape(portal, p_shape); - shape = p_shape; - update_gizmo(); -} - -Vector<Point2> Portal::get_shape() const { - - return shape; -} - -void Portal::set_connect_range(float p_range) { - - connect_range = p_range; - //VisualServer::get_singleton()->portal_set_connect_range(portal,p_range); -} - -float Portal::get_connect_range() const { - - return connect_range; -} - -void Portal::set_enabled(bool p_enabled) { - - enabled = p_enabled; - VisualServer::get_singleton()->portal_set_enabled(portal, enabled); -} - -bool Portal::is_enabled() const { - - return enabled; -} - -void Portal::set_disable_distance(float p_distance) { - - disable_distance = p_distance; - VisualServer::get_singleton()->portal_set_disable_distance(portal, disable_distance); -} -float Portal::get_disable_distance() const { - - return disable_distance; -} - -void Portal::set_disabled_color(const Color &p_disabled_color) { - - disabled_color = p_disabled_color; - VisualServer::get_singleton()->portal_set_disabled_color(portal, disabled_color); -} - -Color Portal::get_disabled_color() const { - - return disabled_color; -} - -void Portal::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_shape", "points"), &Portal::set_shape); - ClassDB::bind_method(D_METHOD("get_shape"), &Portal::get_shape); - - ClassDB::bind_method(D_METHOD("set_enabled", "enable"), &Portal::set_enabled); - ClassDB::bind_method(D_METHOD("is_enabled"), &Portal::is_enabled); - - ClassDB::bind_method(D_METHOD("set_disable_distance", "distance"), &Portal::set_disable_distance); - ClassDB::bind_method(D_METHOD("get_disable_distance"), &Portal::get_disable_distance); - - ClassDB::bind_method(D_METHOD("set_disabled_color", "color"), &Portal::set_disabled_color); - ClassDB::bind_method(D_METHOD("get_disabled_color"), &Portal::get_disabled_color); - - ClassDB::bind_method(D_METHOD("set_connect_range", "range"), &Portal::set_connect_range); - ClassDB::bind_method(D_METHOD("get_connect_range"), &Portal::get_connect_range); -} - -Portal::Portal() { - - portal = VisualServer::get_singleton()->portal_create(); - Vector<Point2> points; - points.push_back(Point2(-1, 1)); - points.push_back(Point2(1, 1)); - points.push_back(Point2(1, -1)); - points.push_back(Point2(-1, -1)); - set_shape(points); // default shape - - set_connect_range(0.8); - set_disable_distance(50); - set_enabled(true); - - set_base(portal); -} - -Portal::~Portal() { - - VisualServer::get_singleton()->free(portal); -} -#endif diff --git a/scene/3d/portal.h b/scene/3d/portal.h deleted file mode 100644 index 04af3a750c..0000000000 --- a/scene/3d/portal.h +++ /dev/null @@ -1,88 +0,0 @@ -/*************************************************************************/ -/* portal.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef PORTAL_H -#define PORTAL_H - -#include "scene/3d/visual_instance.h" - -/* Portal Logic: - If a portal is placed next (very close to) a similar, opposing portal, they automatically connect, - otherwise, a portal connects to the parent room -*/ -// FIXME: This will be redone and replaced by area portals, left for reference -// since a new class with this name will have to exist and want to reuse the gizmos -#if 0 -class Portal : public VisualInstance { - - GDCLASS(Portal, VisualInstance); - - RID portal; - Vector<Point2> shape; - - bool enabled; - float disable_distance; - Color disabled_color; - float connect_range; - - AABB aabb; - -protected: - bool _set(const StringName &p_name, const Variant &p_value); - bool _get(const StringName &p_name, Variant &r_ret) const; - void _get_property_list(List<PropertyInfo> *p_list) const; - - static void _bind_methods(); - -public: - virtual AABB get_aabb() const; - virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const; - - void set_enabled(bool p_enabled); - bool is_enabled() const; - - void set_disable_distance(float p_distance); - float get_disable_distance() const; - - void set_disabled_color(const Color &p_disabled_color); - Color get_disabled_color() const; - - void set_shape(const Vector<Point2> &p_shape); - Vector<Point2> get_shape() const; - - void set_connect_range(float p_range); - float get_connect_range() const; - - Portal(); - ~Portal(); -}; - -#endif -#endif diff --git a/scene/3d/position_3d.cpp b/scene/3d/position_3d.cpp index 18de105eee..e63c588e28 100644 --- a/scene/3d/position_3d.cpp +++ b/scene/3d/position_3d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/position_3d.h b/scene/3d/position_3d.h index 21361592d1..cd5080c95a 100644 --- a/scene/3d/position_3d.h +++ b/scene/3d/position_3d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/proximity_group.cpp b/scene/3d/proximity_group.cpp index 96dc3304f2..2e1478b1cf 100644 --- a/scene/3d/proximity_group.cpp +++ b/scene/3d/proximity_group.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/proximity_group.h b/scene/3d/proximity_group.h index bd11e31031..9ff8853178 100644 --- a/scene/3d/proximity_group.h +++ b/scene/3d/proximity_group.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/ray_cast.cpp b/scene/3d/ray_cast.cpp index 30eed8f1a7..fbe3cd7a3e 100644 --- a/scene/3d/ray_cast.cpp +++ b/scene/3d/ray_cast.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/ray_cast.h b/scene/3d/ray_cast.h index 43d55adb98..5cebfe3ac2 100644 --- a/scene/3d/ray_cast.h +++ b/scene/3d/ray_cast.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp index c34771d9f1..2a5a84741f 100644 --- a/scene/3d/reflection_probe.cpp +++ b/scene/3d/reflection_probe.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/reflection_probe.h b/scene/3d/reflection_probe.h index 48d65b79f7..28ca680e9f 100644 --- a/scene/3d/reflection_probe.h +++ b/scene/3d/reflection_probe.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/remote_transform.cpp b/scene/3d/remote_transform.cpp index 76b0b0c92f..983af7a9ec 100644 --- a/scene/3d/remote_transform.cpp +++ b/scene/3d/remote_transform.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/remote_transform.h b/scene/3d/remote_transform.h index 07e01284e5..02e448832f 100644 --- a/scene/3d/remote_transform.h +++ b/scene/3d/remote_transform.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/room_instance.cpp b/scene/3d/room_instance.cpp deleted file mode 100644 index 073fe4f1da..0000000000 --- a/scene/3d/room_instance.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/*************************************************************************/ -/* room_instance.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "room_instance.h" - -#include "servers/visual_server.h" - -// FIXME: Will be removed, kept as reference for new implementation -#if 0 -#include "core/math/geometry.h" -#include "core/project_settings.h" -#include "scene/resources/surface_tool.h" - -void Room::_notification(int p_what) { - - switch (p_what) { - case NOTIFICATION_ENTER_WORLD: { - // go find parent level - Node *parent_room = get_parent(); - level = 0; - - while (parent_room) { - - Room *r = Object::cast_to<Room>(parent_room); - if (r) { - - level = r->level + 1; - break; - } - - parent_room = parent_room->get_parent(); - } - - } break; - case NOTIFICATION_TRANSFORM_CHANGED: { - } break; - case NOTIFICATION_EXIT_WORLD: { - - } break; - } -} - -AABB Room::get_aabb() const { - - if (room.is_null()) - return AABB(); - - return AABB(); -} - -PoolVector<Face3> Room::get_faces(uint32_t p_usage_flags) const { - - return PoolVector<Face3>(); -} - -void Room::set_room(const Ref<RoomBounds> &p_room) { - - room = p_room; - update_gizmo(); - - if (room.is_valid()) { - - set_base(room->get_rid()); - } else { - set_base(RID()); - } - - if (!is_inside_tree()) - return; - - propagate_notification(NOTIFICATION_AREA_CHANGED); - update_gizmo(); -} - -Ref<RoomBounds> Room::get_room() const { - - return room; -} - -void Room::_parse_node_faces(PoolVector<Face3> &all_faces, const Node *p_node) const { - - const VisualInstance *vi = Object::cast_to<VisualInstance>(p_node); - - if (vi) { - PoolVector<Face3> faces = vi->get_faces(FACES_ENCLOSING); - - if (faces.size()) { - int old_len = all_faces.size(); - all_faces.resize(all_faces.size() + faces.size()); - int new_len = all_faces.size(); - PoolVector<Face3>::Write all_facesw = all_faces.write(); - Face3 *all_facesptr = all_facesw.ptr(); - - PoolVector<Face3>::Read facesr = faces.read(); - const Face3 *facesptr = facesr.ptr(); - - Transform tr = vi->get_relative_transform(this); - - for (int i = old_len; i < new_len; i++) { - - Face3 f = facesptr[i - old_len]; - for (int j = 0; j < 3; j++) - f.vertex[j] = tr.xform(f.vertex[j]); - all_facesptr[i] = f; - } - } - } - - for (int i = 0; i < p_node->get_child_count(); i++) { - - _parse_node_faces(all_faces, p_node->get_child(i)); - } -} - -void Room::_bounds_changed() { - - update_gizmo(); -} - -void Room::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_room", "room"), &Room::set_room); - ClassDB::bind_method(D_METHOD("get_room"), &Room::get_room); - - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "room/room", PROPERTY_HINT_RESOURCE_TYPE, "Area"), "set_room", "get_room"); -} - -Room::Room() { - - // sound_enabled=false; - - level = 0; -} - -Room::~Room() { -} -#endif diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp index ae79b4eebf..4089e0c23b 100644 --- a/scene/3d/skeleton.cpp +++ b/scene/3d/skeleton.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,6 +32,7 @@ #include "core/message_queue.h" +#include "core/engine.h" #include "core/project_settings.h" #include "scene/3d/physics_body.h" #include "scene/resources/surface_tool.h" @@ -181,7 +182,7 @@ void Skeleton::_update_process_order() { if (bonesptr[i].parent >= len) { //validate this just in case - ERR_PRINTS("Bone " + itos(i) + " has invalid parent: " + itos(bonesptr[i].parent)); + ERR_PRINT("Bone " + itos(i) + " has invalid parent: " + itos(bonesptr[i].parent)); bonesptr[i].parent = -1; } order[i] = i; @@ -332,6 +333,27 @@ void Skeleton::_notification(int p_what) { dirty = false; } break; + +#ifndef _3D_DISABLED + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { + // This is active only if the skeleton animates the physical bones + // and the state of the bone is not active. + if (animate_physical_bones) { + for (int i = 0; i < bones.size(); i += 1) { + if (bones[i].physical_bone) { + if (bones[i].physical_bone->is_simulating_physics() == false) { + bones[i].physical_bone->reset_to_rest_position(); + } + } + } + } + } break; + case NOTIFICATION_READY: { + if (Engine::get_singleton()->is_editor_hint()) { + set_physics_process_internal(true); + } + } break; +#endif } } @@ -584,6 +606,27 @@ void Skeleton::localize_rests() { #ifndef _3D_DISABLED +void Skeleton::set_animate_physical_bones(bool p_animate) { + animate_physical_bones = p_animate; + + if (Engine::get_singleton()->is_editor_hint() == false) { + bool sim = false; + for (int i = 0; i < bones.size(); i += 1) { + if (bones[i].physical_bone) { + bones[i].physical_bone->reset_physics_simulation_state(); + if (bones[i].physical_bone->is_simulating_physics()) { + sim = true; + } + } + } + set_physics_process_internal(sim == false && p_animate); + } +} + +bool Skeleton::get_animate_physical_bones() const { + return animate_physical_bones; +} + 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); @@ -653,12 +696,14 @@ void _pb_stop_simulation(Node *p_node) { PhysicalBone *pb = Object::cast_to<PhysicalBone>(p_node); if (pb) { pb->set_simulate_physics(false); - pb->set_static_body(false); } } void Skeleton::physical_bones_stop_simulation() { _pb_stop_simulation(this); + if (Engine::get_singleton()->is_editor_hint() == false && animate_physical_bones) { + set_physics_process_internal(true); + } } void _pb_start_simulation(const Skeleton *p_skeleton, Node *p_node, const Vector<int> &p_sim_bones) { @@ -669,24 +714,17 @@ void _pb_start_simulation(const Skeleton *p_skeleton, Node *p_node, const Vector PhysicalBone *pb = Object::cast_to<PhysicalBone>(p_node); if (pb) { - bool sim = false; for (int i = p_sim_bones.size() - 1; 0 <= i; --i) { if (p_sim_bones[i] == pb->get_bone_id() || p_skeleton->is_bone_parent_of(pb->get_bone_id(), p_sim_bones[i])) { - sim = true; + pb->set_simulate_physics(true); break; } } - - pb->set_simulate_physics(true); - if (sim) { - pb->set_static_body(false); - } else { - pb->set_static_body(true); - } } } void Skeleton::physical_bones_start_simulation_on(const Array &p_bones) { + set_physics_process_internal(false); Vector<int> sim_bones; if (p_bones.size() <= 0) { @@ -836,11 +874,15 @@ void Skeleton::_bind_methods() { #ifndef _3D_DISABLED + ClassDB::bind_method(D_METHOD("set_animate_physical_bones"), &Skeleton::set_animate_physical_bones); + ClassDB::bind_method(D_METHOD("get_animate_physical_bones"), &Skeleton::get_animate_physical_bones); + 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); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "animate_physical_bones"), "set_animate_physical_bones", "get_animate_physical_bones"); #endif // _3D_DISABLED BIND_CONSTANT(NOTIFICATION_UPDATE_SKELETON); @@ -848,6 +890,7 @@ void Skeleton::_bind_methods() { Skeleton::Skeleton() { + animate_physical_bones = true; dirty = false; process_order_dirty = true; } diff --git a/scene/3d/skeleton.h b/scene/3d/skeleton.h index 824d9567fa..9599510850 100644 --- a/scene/3d/skeleton.h +++ b/scene/3d/skeleton.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -115,6 +115,7 @@ private: } }; + bool animate_physical_bones; Vector<Bone> bones; Vector<int> process_order; bool process_order_dirty; @@ -199,6 +200,9 @@ public: #ifndef _3D_DISABLED // Physical bone API + void set_animate_physical_bones(bool p_animate); + bool get_animate_physical_bones() const; + void bind_physical_bone_to_bone(int p_bone, PhysicalBone *p_physical_bone); void unbind_physical_bone_from_bone(int p_bone); diff --git a/scene/3d/soft_body.cpp b/scene/3d/soft_body.cpp index 6883da7f6d..435bef7247 100644 --- a/scene/3d/soft_body.cpp +++ b/scene/3d/soft_body.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -247,7 +247,7 @@ bool SoftBody::_get_property_pinned_points(int p_item, const String &p_what, Var } void SoftBody::_changed_callback(Object *p_changed, const char *p_prop) { - update_physics_server(); + prepare_physics_server(); _reset_points_offsets(); #ifdef TOOLS_ENABLED if (p_changed == this) { @@ -267,7 +267,7 @@ void SoftBody::_notification(int p_what) { RID space = get_world()->get_space(); PhysicsServer::get_singleton()->soft_body_set_space(physics_rid, space); - update_physics_server(); + prepare_physics_server(); } break; case NOTIFICATION_READY: { if (!parent_collision_ignore.is_empty()) @@ -290,21 +290,6 @@ void SoftBody::_notification(int p_what) { set_notify_transform(true); } break; - case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { - - if (!simulation_started) - return; - - _update_cache_pin_points_datas(); - // Submit bone attachment - const int pinned_points_indices_size = pinned_points.size(); - PoolVector<PinnedPoint>::Read r = pinned_points.read(); - for (int i = 0; i < pinned_points_indices_size; ++i) { - if (r[i].spatial_attachment) { - PhysicsServer::get_singleton()->soft_body_move_point(physics_rid, r[i].point_index, r[i].spatial_attachment->get_global_transform().xform(r[i].offset)); - } - } - } break; case NOTIFICATION_VISIBILITY_CHANGED: { _update_pickable(); @@ -421,6 +406,21 @@ String SoftBody::get_configuration_warning() const { return warning; } +void SoftBody::_update_physics_server() { + if (!simulation_started) + return; + + _update_cache_pin_points_datas(); + // Submit bone attachment + const int pinned_points_indices_size = pinned_points.size(); + PoolVector<PinnedPoint>::Read r = pinned_points.read(); + for (int i = 0; i < pinned_points_indices_size; ++i) { + if (r[i].spatial_attachment) { + PhysicsServer::get_singleton()->soft_body_move_point(physics_rid, r[i].point_index, r[i].spatial_attachment->get_global_transform().xform(r[i].offset)); + } + } +} + void SoftBody::_draw_soft_mesh() { if (get_mesh().is_null()) return; @@ -435,6 +435,8 @@ void SoftBody::_draw_soft_mesh() { call_deferred("set_transform", Transform()); } + _update_physics_server(); + visual_server_handler.open(); PhysicsServer::get_singleton()->soft_body_update_visual_server(physics_rid, &visual_server_handler); visual_server_handler.close(); @@ -442,7 +444,7 @@ void SoftBody::_draw_soft_mesh() { visual_server_handler.commit_changes(); } -void SoftBody::update_physics_server() { +void SoftBody::prepare_physics_server() { if (Engine::get_singleton()->is_editor_hint()) { @@ -706,8 +708,6 @@ SoftBody::SoftBody() : ray_pickable(true) { PhysicsServer::get_singleton()->body_attach_object_instance_id(physics_rid, get_instance_id()); - //set_notify_transform(true); - set_physics_process_internal(true); } SoftBody::~SoftBody() { diff --git a/scene/3d/soft_body.h b/scene/3d/soft_body.h index ee455f8dab..800db12594 100644 --- a/scene/3d/soft_body.h +++ b/scene/3d/soft_body.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -116,10 +116,11 @@ protected: virtual String get_configuration_warning() const; protected: + void _update_physics_server(); void _draw_soft_mesh(); public: - void update_physics_server(); + void prepare_physics_server(); void become_mesh_owner(); void set_collision_mask(uint32_t p_mask); diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp index 9a659ef4af..f1911348ce 100644 --- a/scene/3d/spatial.cpp +++ b/scene/3d/spatial.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -125,6 +125,7 @@ void Spatial::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { + ERR_FAIL_COND(!get_tree()); Node *p = get_parent(); if (p) @@ -322,6 +323,7 @@ Transform Spatial::get_relative_transform(const Node *p_parent) const { void Spatial::set_translation(const Vector3 &p_translation) { data.local_transform.origin = p_translation; + _change_notify("transform"); _propagate_transform_changed(this); if (data.notify_local_transform) { notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); @@ -337,6 +339,7 @@ void Spatial::set_rotation(const Vector3 &p_euler_rad) { data.rotation = p_euler_rad; data.dirty |= DIRTY_LOCAL; + _change_notify("transform"); _propagate_transform_changed(this); if (data.notify_local_transform) { notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); @@ -357,6 +360,7 @@ void Spatial::set_scale(const Vector3 &p_scale) { data.scale = p_scale; data.dirty |= DIRTY_LOCAL; + _change_notify("transform"); _propagate_transform_changed(this); if (data.notify_local_transform) { notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); diff --git a/scene/3d/spatial.h b/scene/3d/spatial.h index eea2696767..9d4705700b 100644 --- a/scene/3d/spatial.h +++ b/scene/3d/spatial.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/spatial_velocity_tracker.cpp b/scene/3d/spatial_velocity_tracker.cpp index 97517be53b..ec1bb1f991 100644 --- a/scene/3d/spatial_velocity_tracker.cpp +++ b/scene/3d/spatial_velocity_tracker.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/spatial_velocity_tracker.h b/scene/3d/spatial_velocity_tracker.h index 8260cf3f06..92b527b93c 100644 --- a/scene/3d/spatial_velocity_tracker.h +++ b/scene/3d/spatial_velocity_tracker.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/spring_arm.cpp b/scene/3d/spring_arm.cpp index f3665d251b..bce0535d64 100644 --- a/scene/3d/spring_arm.cpp +++ b/scene/3d/spring_arm.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/spring_arm.h b/scene/3d/spring_arm.h index 35df56f06e..1a12370564 100644 --- a/scene/3d/spring_arm.h +++ b/scene/3d/spring_arm.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index adcd80b0ab..a4c81b864d 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h index 065931de84..ddbade147c 100644 --- a/scene/3d/sprite_3d.h +++ b/scene/3d/sprite_3d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/vehicle_body.cpp b/scene/3d/vehicle_body.cpp index 98e68cfbda..92b17d5056 100644 --- a/scene/3d/vehicle_body.cpp +++ b/scene/3d/vehicle_body.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/vehicle_body.h b/scene/3d/vehicle_body.h index 914bfd54bd..c05ea30f94 100644 --- a/scene/3d/vehicle_body.h +++ b/scene/3d/vehicle_body.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/visibility_notifier.cpp b/scene/3d/visibility_notifier.cpp index 3014432d59..510442dc1c 100644 --- a/scene/3d/visibility_notifier.cpp +++ b/scene/3d/visibility_notifier.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -240,7 +240,6 @@ void VisibilityEnabler::_node_removed(Node *p_node) { if (!visible) _change_node_state(p_node, true); - p_node->disconnect(SceneStringNames::get_singleton()->tree_exiting, this, "_node_removed"); nodes.erase(p_node); } diff --git a/scene/3d/visibility_notifier.h b/scene/3d/visibility_notifier.h index ff4424300c..71fdfdb78c 100644 --- a/scene/3d/visibility_notifier.h +++ b/scene/3d/visibility_notifier.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp index d1de0c56a7..4574dfac5f 100644 --- a/scene/3d/visual_instance.cpp +++ b/scene/3d/visual_instance.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/visual_instance.h b/scene/3d/visual_instance.h index 63d15680aa..f115748952 100644 --- a/scene/3d/visual_instance.h +++ b/scene/3d/visual_instance.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/voxel_light_baker.cpp b/scene/3d/voxel_light_baker.cpp index 8e09930aed..c1ec59d49f 100644 --- a/scene/3d/voxel_light_baker.cpp +++ b/scene/3d/voxel_light_baker.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,6 +29,7 @@ /*************************************************************************/ #include "voxel_light_baker.h" + #include "core/os/os.h" #include "core/os/threaded_array_processor.h" @@ -1594,10 +1595,10 @@ Vector3 VoxelLightBaker::_compute_pixel_light_at_pos(const Vector3 &p_pos, const case BAKE_QUALITY_LOW: { //default quality static const Vector3 dirs[4] = { - Vector3(0.707107, 0, 0.707107), - Vector3(0, 0.707107, 0.707107), - Vector3(-0.707107, 0, 0.707107), - Vector3(0, -0.707107, 0.707107) + Vector3(Math_SQRT12, 0, Math_SQRT12), + Vector3(0, Math_SQRT12, Math_SQRT12), + Vector3(-Math_SQRT12, 0, Math_SQRT12), + Vector3(0, -Math_SQRT12, Math_SQRT12) }; static const float weights[4] = { 0.25, 0.25, 0.25, 0.25 }; @@ -2118,8 +2119,7 @@ Error VoxelLightBaker::make_lightmap(const Transform &p_xform, Ref<Mesh> &p_mesh } } -// Enable for debugging -#if 0 +#if 0 // Enable for debugging. { PoolVector<uint8_t> img; int ls = lightmap.size(); diff --git a/scene/3d/voxel_light_baker.h b/scene/3d/voxel_light_baker.h index 2e2efc62ff..7e78a19830 100644 --- a/scene/3d/voxel_light_baker.h +++ b/scene/3d/voxel_light_baker.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/world_environment.cpp b/scene/3d/world_environment.cpp index 8d46b4161d..c8d7382e81 100644 --- a/scene/3d/world_environment.cpp +++ b/scene/3d/world_environment.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/world_environment.h b/scene/3d/world_environment.h index 656e16371f..6e89fe8517 100644 --- a/scene/3d/world_environment.h +++ b/scene/3d/world_environment.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/animation/animation_blend_space_1d.cpp b/scene/animation/animation_blend_space_1d.cpp index 7fe544eaab..0f55682427 100644 --- a/scene/animation/animation_blend_space_1d.cpp +++ b/scene/animation/animation_blend_space_1d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/animation/animation_blend_space_1d.h b/scene/animation/animation_blend_space_1d.h index 2e2d848450..da3608e06d 100644 --- a/scene/animation/animation_blend_space_1d.h +++ b/scene/animation/animation_blend_space_1d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/animation/animation_blend_space_2d.cpp b/scene/animation/animation_blend_space_2d.cpp index b04eefbe31..d749959377 100644 --- a/scene/animation/animation_blend_space_2d.cpp +++ b/scene/animation/animation_blend_space_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/animation/animation_blend_space_2d.h b/scene/animation/animation_blend_space_2d.h index 66ba9b0db7..7d197ef920 100644 --- a/scene/animation/animation_blend_space_2d.h +++ b/scene/animation/animation_blend_space_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp index 6f67d01a1c..5c284cb483 100644 --- a/scene/animation/animation_blend_tree.cpp +++ b/scene/animation/animation_blend_tree.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,6 +29,7 @@ /*************************************************************************/ #include "animation_blend_tree.h" + #include "scene/scene_string_names.h" void AnimationNodeAnimation::set_animation(const StringName &p_name) { @@ -718,21 +719,6 @@ String AnimationNodeTransition::get_input_caption(int p_input) const { return inputs[p_input].name; } -#if 0 - Ref<AnimationNodeBlendTree> tree = get_parent(); - - if (tree.is_valid() && current >= 0) { - prev = current; - prev_xfading = xfade; - time = 0; - current = p_current; - switched = true; - _change_notify("current"); - } else { - current = p_current; - } -#endif - void AnimationNodeTransition::set_cross_fade_time(float p_fade) { xfade = p_fade; } @@ -846,8 +832,8 @@ void AnimationNodeTransition::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "xfade_time", PROPERTY_HINT_RANGE, "0,120,0.01"), "set_cross_fade_time", "get_cross_fade_time"); for (int i = 0; i < MAX_INPUTS; i++) { - ADD_PROPERTYI(PropertyInfo(Variant::STRING, "input_" + itos(i) + "/name"), "set_input_caption", "get_input_caption", i); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "input_" + itos(i) + "/auto_advance"), "set_input_as_auto_advance", "is_input_set_as_auto_advance", i); + ADD_PROPERTYI(PropertyInfo(Variant::STRING, "input_" + itos(i) + "/name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "set_input_caption", "get_input_caption", i); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "input_" + itos(i) + "/auto_advance", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "set_input_as_auto_advance", "is_input_set_as_auto_advance", i); } } diff --git a/scene/animation/animation_blend_tree.h b/scene/animation/animation_blend_tree.h index a6ef78d82e..7ebe3f5444 100644 --- a/scene/animation/animation_blend_tree.h +++ b/scene/animation/animation_blend_tree.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/animation/animation_cache.cpp b/scene/animation/animation_cache.cpp index 5956609244..8d1ffb43cc 100644 --- a/scene/animation/animation_cache.cpp +++ b/scene/animation/animation_cache.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/animation/animation_cache.h b/scene/animation/animation_cache.h index ac668b7796..26ad9dfee5 100644 --- a/scene/animation/animation_cache.h +++ b/scene/animation/animation_cache.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp index 65bf1e0134..59d0d9e87f 100644 --- a/scene/animation/animation_node_state_machine.cpp +++ b/scene/animation/animation_node_state_machine.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -312,27 +312,36 @@ float AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_st bool play_start = false; if (start_request != StringName()) { - if (start_request_travel) { if (!playing) { - String node_name = start_request; - start_request = StringName(); - ERR_FAIL_V_MSG(0, "Can't travel to '" + node_name + "' if state machine is not playing."); - } - - if (!_travel(p_state_machine, start_request)) { - //can't travel, then teleport - path.clear(); - current = start_request; + if (!stop_request && p_state_machine->start_node) { + // can restart, just postpone traveling + path.clear(); + current = p_state_machine->start_node; + playing = true; + play_start = true; + } else { + // stopped, invalid state + String node_name = start_request; + start_request = StringName(); //clear start request + ERR_FAIL_V_MSG(0, "Can't travel to '" + node_name + "' if state machine is not playing."); + } + } else { + if (!_travel(p_state_machine, start_request)) { + // can't travel, then teleport + path.clear(); + current = start_request; + } + start_request = StringName(); //clear start request } } else { + // teleport to start path.clear(); current = start_request; playing = true; play_start = true; + start_request = StringName(); //clear start request } - - start_request = StringName(); //clear start request } bool do_start = (p_seek && p_time == 0) || play_start || current == StringName(); diff --git a/scene/animation/animation_node_state_machine.h b/scene/animation/animation_node_state_machine.h index 26909a326e..55c9c3f00e 100644 --- a/scene/animation/animation_node_state_machine.h +++ b/scene/animation/animation_node_state_machine.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index f9bf129b59..7ec7037dd7 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -493,7 +493,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float pa->object->set_indexed(pa->subpath, value, &valid); //you are not speshul #ifdef DEBUG_ENABLED if (!valid) { - ERR_PRINTS("Failed setting track value '" + String(pa->owner->path) + "'. Check if property exists or the type of key is valid. Animation '" + a->get_name() + "' at node '" + get_path() + "'."); + ERR_PRINT("Failed setting track value '" + String(pa->owner->path) + "'. Check if property exists or the type of key is valid. Animation '" + a->get_name() + "' at node '" + get_path() + "'."); } #endif @@ -501,7 +501,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float case SP_NODE2D_POS: { #ifdef DEBUG_ENABLED if (value.get_type() != Variant::VECTOR2) { - ERR_PRINTS("Position key at time " + rtos(p_time) + " in Animation Track '" + String(pa->owner->path) + "' not of type Vector2(). Animation '" + a->get_name() + "' at node '" + get_path() + "'."); + ERR_PRINT("Position key at time " + rtos(p_time) + " in Animation Track '" + String(pa->owner->path) + "' not of type Vector2(). Animation '" + a->get_name() + "' at node '" + get_path() + "'."); } #endif static_cast<Node2D *>(pa->object)->set_position(value); @@ -509,7 +509,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float case SP_NODE2D_ROT: { #ifdef DEBUG_ENABLED if (value.is_num()) { - ERR_PRINTS("Rotation key at time " + rtos(p_time) + " in Animation Track '" + String(pa->owner->path) + "' not numerical. Animation '" + a->get_name() + "' at node '" + get_path() + "'."); + ERR_PRINT("Rotation key at time " + rtos(p_time) + " in Animation Track '" + String(pa->owner->path) + "' not numerical. Animation '" + a->get_name() + "' at node '" + get_path() + "'."); } #endif @@ -518,7 +518,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float case SP_NODE2D_SCALE: { #ifdef DEBUG_ENABLED if (value.get_type() != Variant::VECTOR2) { - ERR_PRINTS("Scale key at time " + rtos(p_time) + " in Animation Track '" + String(pa->owner->path) + "' not of type Vector2()." + a->get_name() + "' at node '" + get_path() + "'."); + ERR_PRINT("Scale key at time " + rtos(p_time) + " in Animation Track '" + String(pa->owner->path) + "' not of type Vector2()." + a->get_name() + "' at node '" + get_path() + "'."); } #endif @@ -553,7 +553,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float ERR_CONTINUE(s > VARIANT_ARG_MAX); #ifdef DEBUG_ENABLED if (!nc->node->has_method(method)) { - ERR_PRINTS("Invalid method call '" + method + "'. '" + a->get_name() + "' at node '" + get_path() + "'."); + ERR_PRINT("Invalid method call '" + method + "'. '" + a->get_name() + "' at node '" + get_path() + "'."); } #endif @@ -884,7 +884,7 @@ void AnimationPlayer::_animation_update_transforms() { pa->object->set_indexed(pa->subpath, pa->value_accum, &valid); //you are not speshul #ifdef DEBUG_ENABLED if (!valid) { - ERR_PRINTS("Failed setting key at time " + rtos(playback.current.pos) + " in Animation '" + get_current_animation() + "' at Node '" + get_path() + "', Track '" + String(pa->owner->path) + "'. Check if property exists or the type of key is right for the property"); + ERR_PRINT("Failed setting key at time " + rtos(playback.current.pos) + " in Animation '" + get_current_animation() + "' at Node '" + get_path() + "', Track '" + String(pa->owner->path) + "'. Check if property exists or the type of key is right for the property"); } #endif @@ -892,7 +892,7 @@ void AnimationPlayer::_animation_update_transforms() { case SP_NODE2D_POS: { #ifdef DEBUG_ENABLED if (pa->value_accum.get_type() != Variant::VECTOR2) { - ERR_PRINTS("Position key at time " + rtos(playback.current.pos) + " in Animation '" + get_current_animation() + "' at Node '" + get_path() + "', Track '" + String(pa->owner->path) + "' not of type Vector2()"); + ERR_PRINT("Position key at time " + rtos(playback.current.pos) + " in Animation '" + get_current_animation() + "' at Node '" + get_path() + "', Track '" + String(pa->owner->path) + "' not of type Vector2()"); } #endif static_cast<Node2D *>(pa->object)->set_position(pa->value_accum); @@ -900,7 +900,7 @@ void AnimationPlayer::_animation_update_transforms() { case SP_NODE2D_ROT: { #ifdef DEBUG_ENABLED if (pa->value_accum.is_num()) { - ERR_PRINTS("Rotation key at time " + rtos(playback.current.pos) + " in Animation '" + get_current_animation() + "' at Node '" + get_path() + "', Track '" + String(pa->owner->path) + "' not numerical"); + ERR_PRINT("Rotation key at time " + rtos(playback.current.pos) + " in Animation '" + get_current_animation() + "' at Node '" + get_path() + "', Track '" + String(pa->owner->path) + "' not numerical"); } #endif @@ -909,7 +909,7 @@ void AnimationPlayer::_animation_update_transforms() { case SP_NODE2D_SCALE: { #ifdef DEBUG_ENABLED if (pa->value_accum.get_type() != Variant::VECTOR2) { - ERR_PRINTS("Scale key at time " + rtos(playback.current.pos) + " in Animation '" + get_current_animation() + "' at Node '" + get_path() + "', Track '" + String(pa->owner->path) + "' not of type Vector2()"); + ERR_PRINT("Scale key at time " + rtos(playback.current.pos) + " in Animation '" + get_current_animation() + "' at Node '" + get_path() + "', Track '" + String(pa->owner->path) + "' not of type Vector2()"); } #endif diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index 320fd2084c..06f762e63e 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index eb152bc41e..c28f8dc824 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -49,7 +49,7 @@ void AnimationNode::get_parameter_list(List<PropertyInfo> *r_list) const { Variant AnimationNode::get_parameter_default_value(const StringName &p_parameter) const { if (get_script_instance()) { - return get_script_instance()->call("get_parameter_default_value"); + return get_script_instance()->call("get_parameter_default_value", p_parameter); } return Variant(); } @@ -397,7 +397,7 @@ void AnimationNode::_validate_property(PropertyInfo &property) const { Ref<AnimationNode> AnimationNode::get_child_by_name(const StringName &p_name) { if (get_script_instance()) { - return get_script_instance()->call("get_child_by_name"); + return get_script_instance()->call("get_child_by_name", p_name); } return Ref<AnimationNode>(); } @@ -578,7 +578,7 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { Node *child = parent->get_node_and_resource(path, resource, leftover_path); if (!child) { - ERR_PRINTS("AnimationTree: '" + String(E->get()) + "', couldn't resolve track: '" + String(path) + "'"); + ERR_PRINT("AnimationTree: '" + String(E->get()) + "', couldn't resolve track: '" + String(path) + "'"); continue; } @@ -608,7 +608,7 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { Spatial *spatial = Object::cast_to<Spatial>(child); if (!spatial) { - ERR_PRINTS("AnimationTree: '" + String(E->get()) + "', transform track does not point to spatial: '" + String(path) + "'"); + ERR_PRINT("AnimationTree: '" + String(E->get()) + "', transform track does not point to spatial: '" + String(path) + "'"); continue; } diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h index e22d6e4c2d..0a8dc8109f 100644 --- a/scene/animation/animation_tree.h +++ b/scene/animation/animation_tree.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp deleted file mode 100644 index ba5936562a..0000000000 --- a/scene/animation/animation_tree_player.cpp +++ /dev/null @@ -1,1866 +0,0 @@ -/*************************************************************************/ -/* animation_tree_player.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "animation_tree_player.h" -#include "animation_player.h" - -#include "scene/scene_string_names.h" - -void AnimationTreePlayer::set_animation_process_mode(AnimationProcessMode p_mode) { - - if (animation_process_mode == p_mode) - return; - - bool pr = processing; - if (pr) - _set_process(false); - animation_process_mode = p_mode; - if (pr) - _set_process(true); -} - -AnimationTreePlayer::AnimationProcessMode AnimationTreePlayer::get_animation_process_mode() const { - - return animation_process_mode; -} - -void AnimationTreePlayer::_set_process(bool p_process, bool p_force) { - if (processing == p_process && !p_force) - return; - - switch (animation_process_mode) { - - case ANIMATION_PROCESS_PHYSICS: set_physics_process_internal(p_process && active); break; - case ANIMATION_PROCESS_IDLE: set_process_internal(p_process && active); break; - } - - processing = p_process; -} - -bool AnimationTreePlayer::_set(const StringName &p_name, const Variant &p_value) { - - if (String(p_name) == "base_path") { - set_base_path(p_value); - return true; - } - - if (String(p_name) == "master_player") { - set_master_player(p_value); - return true; - } - - if (String(p_name) == SceneStringNames::get_singleton()->playback_active) { - set_active(p_value); - return true; - } - - if (String(p_name) != "data") - return false; - - Dictionary data = p_value; - - Array nodes = data.get_valid("nodes"); - - for (int i = 0; i < nodes.size(); i++) { - - Dictionary node = nodes[i]; - - StringName id = node.get_valid("id"); - Point2 pos = node.get_valid("position"); - - NodeType nt = NODE_MAX; - String type = node.get_valid("type"); - - if (type == "output") - nt = NODE_OUTPUT; - else if (type == "animation") - nt = NODE_ANIMATION; - else if (type == "oneshot") - nt = NODE_ONESHOT; - else if (type == "mix") - nt = NODE_MIX; - else if (type == "blend2") - nt = NODE_BLEND2; - else if (type == "blend3") - nt = NODE_BLEND3; - else if (type == "blend4") - nt = NODE_BLEND4; - else if (type == "timescale") - nt = NODE_TIMESCALE; - else if (type == "timeseek") - nt = NODE_TIMESEEK; - else if (type == "transition") - nt = NODE_TRANSITION; - - ERR_FAIL_COND_V(nt == NODE_MAX, false); - - if (nt != NODE_OUTPUT) - add_node(nt, id); - node_set_position(id, pos); - - switch (nt) { - case NODE_OUTPUT: { - - } break; - case NODE_ANIMATION: { - - if (node.has("from")) - animation_node_set_master_animation(id, node.get_valid("from")); - else - animation_node_set_animation(id, node.get_valid("animation")); - Array filters = node.get_valid("filter"); - for (int j = 0; j < filters.size(); j++) { - - animation_node_set_filter_path(id, filters[j], true); - } - } break; - case NODE_ONESHOT: { - - oneshot_node_set_fadein_time(id, node.get_valid("fade_in")); - oneshot_node_set_fadeout_time(id, node.get_valid("fade_out")); - oneshot_node_set_mix_mode(id, node.get_valid("mix")); - oneshot_node_set_autorestart(id, node.get_valid("autorestart")); - oneshot_node_set_autorestart_delay(id, node.get_valid("autorestart_delay")); - oneshot_node_set_autorestart_random_delay(id, node.get_valid("autorestart_random_delay")); - Array filters = node.get_valid("filter"); - for (int j = 0; j < filters.size(); j++) { - - oneshot_node_set_filter_path(id, filters[j], true); - } - - } break; - case NODE_MIX: { - mix_node_set_amount(id, node.get_valid("mix")); - } break; - case NODE_BLEND2: { - blend2_node_set_amount(id, node.get_valid("blend")); - Array filters = node.get_valid("filter"); - for (int j = 0; j < filters.size(); j++) { - - blend2_node_set_filter_path(id, filters[j], true); - } - } break; - case NODE_BLEND3: { - blend3_node_set_amount(id, node.get_valid("blend")); - } break; - case NODE_BLEND4: { - blend4_node_set_amount(id, node.get_valid("blend")); - } break; - case NODE_TIMESCALE: { - timescale_node_set_scale(id, node.get_valid("scale")); - } break; - case NODE_TIMESEEK: { - } break; - case NODE_TRANSITION: { - - transition_node_set_xfade_time(id, node.get_valid("xfade")); - - Array transitions = node.get_valid("transitions"); - transition_node_set_input_count(id, transitions.size()); - - for (int x = 0; x < transitions.size(); x++) { - - Dictionary d = transitions[x]; - bool aa = d.get_valid("auto_advance"); - transition_node_set_input_auto_advance(id, x, aa); - } - - } break; - default: { - }; - } - } - - Array connections = data.get_valid("connections"); - ERR_FAIL_COND_V(connections.size() % 3, false); - - int cc = connections.size() / 3; - - for (int i = 0; i < cc; i++) { - - StringName src = connections[i * 3 + 0]; - StringName dst = connections[i * 3 + 1]; - int dst_in = connections[i * 3 + 2]; - connect_nodes(src, dst, dst_in); - } - - set_active(data.get_valid("active")); - set_master_player(data.get_valid("master")); - - return true; -} - -bool AnimationTreePlayer::_get(const StringName &p_name, Variant &r_ret) const { - - if (String(p_name) == "base_path") { - r_ret = base_path; - return true; - } - - if (String(p_name) == "master_player") { - r_ret = master; - return true; - } - - if (String(p_name) == "playback/active") { - r_ret = is_active(); - return true; - } - - if (String(p_name) != "data") - return false; - - Dictionary data; - - Array nodes; - - for (Map<StringName, NodeBase *>::Element *E = node_map.front(); E; E = E->next()) { - - NodeBase *n = node_map[E->key()]; - - Dictionary node; - node["id"] = E->key(); - node["position"] = n->pos; - - switch (n->type) { - case NODE_OUTPUT: node["type"] = "output"; break; - case NODE_ANIMATION: node["type"] = "animation"; break; - case NODE_ONESHOT: node["type"] = "oneshot"; break; - case NODE_MIX: node["type"] = "mix"; break; - case NODE_BLEND2: node["type"] = "blend2"; break; - case NODE_BLEND3: node["type"] = "blend3"; break; - case NODE_BLEND4: node["type"] = "blend4"; break; - case NODE_TIMESCALE: node["type"] = "timescale"; break; - case NODE_TIMESEEK: node["type"] = "timeseek"; break; - case NODE_TRANSITION: node["type"] = "transition"; break; - default: node["type"] = ""; break; - } - - switch (n->type) { - case NODE_OUTPUT: { - - } break; - case NODE_ANIMATION: { - AnimationNode *an = static_cast<AnimationNode *>(n); - if (master != NodePath() && an->from != "") { - node["from"] = an->from; - } else { - node["animation"] = an->animation; - } - Array k; - List<NodePath> keys; - an->filter.get_key_list(&keys); - k.resize(keys.size()); - int i = 0; - for (List<NodePath>::Element *F = keys.front(); F; F = F->next()) { - k[i++] = F->get(); - } - node["filter"] = k; - } break; - case NODE_ONESHOT: { - OneShotNode *osn = static_cast<OneShotNode *>(n); - node["fade_in"] = osn->fade_in; - node["fade_out"] = osn->fade_out; - node["mix"] = osn->mix; - node["autorestart"] = osn->autorestart; - node["autorestart_delay"] = osn->autorestart_delay; - node["autorestart_random_delay"] = osn->autorestart_random_delay; - - Array k; - List<NodePath> keys; - osn->filter.get_key_list(&keys); - k.resize(keys.size()); - int i = 0; - for (List<NodePath>::Element *F = keys.front(); F; F = F->next()) { - k[i++] = F->get(); - } - node["filter"] = k; - - } break; - case NODE_MIX: { - MixNode *mn = static_cast<MixNode *>(n); - node["mix"] = mn->amount; - } break; - case NODE_BLEND2: { - Blend2Node *bn = static_cast<Blend2Node *>(n); - node["blend"] = bn->value; - Array k; - List<NodePath> keys; - bn->filter.get_key_list(&keys); - k.resize(keys.size()); - int i = 0; - for (List<NodePath>::Element *F = keys.front(); F; F = F->next()) { - k[i++] = F->get(); - } - node["filter"] = k; - - } break; - case NODE_BLEND3: { - Blend3Node *bn = static_cast<Blend3Node *>(n); - node["blend"] = bn->value; - } break; - case NODE_BLEND4: { - Blend4Node *bn = static_cast<Blend4Node *>(n); - node["blend"] = bn->value; - - } break; - case NODE_TIMESCALE: { - TimeScaleNode *tsn = static_cast<TimeScaleNode *>(n); - node["scale"] = tsn->scale; - } break; - case NODE_TIMESEEK: { - } break; - case NODE_TRANSITION: { - - TransitionNode *tn = static_cast<TransitionNode *>(n); - node["xfade"] = tn->xfade; - Array transitions; - - for (int i = 0; i < tn->input_data.size(); i++) { - - Dictionary d; - d["auto_advance"] = tn->input_data[i].auto_advance; - transitions.push_back(d); - } - - node["transitions"] = transitions; - - } break; - default: { - }; - } - - nodes.push_back(node); - } - - data["nodes"] = nodes; - //connectiosn - - List<Connection> connections; - get_connection_list(&connections); - Array connections_arr; - connections_arr.resize(connections.size() * 3); - - int idx = 0; - for (List<Connection>::Element *E = connections.front(); E; E = E->next()) { - - connections_arr.set(idx + 0, E->get().src_node); - connections_arr.set(idx + 1, E->get().dst_node); - connections_arr.set(idx + 2, E->get().dst_input); - - idx += 3; - } - - data["connections"] = connections_arr; - data["active"] = active; - data["master"] = master; - - r_ret = data; - - return true; -} - -void AnimationTreePlayer::_get_property_list(List<PropertyInfo> *p_list) const { - - p_list->push_back(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_NETWORK)); -} - -void AnimationTreePlayer::advance(float p_time) { - - _process_animation(p_time); -} - -void AnimationTreePlayer::_notification(int p_what) { - - switch (p_what) { - - case NOTIFICATION_ENTER_TREE: { - - WARN_DEPRECATED_MSG("AnimationTreePlayer has been deprecated. Use AnimationTree instead."); - - if (!processing) { - //make sure that a previous process state was not saved - //only process if "processing" is set - set_physics_process_internal(false); - set_process_internal(false); - } - } break; - case NOTIFICATION_READY: { - - dirty_caches = true; - if (master != NodePath()) { - _update_sources(); - } - } break; - case NOTIFICATION_INTERNAL_PROCESS: { - - if (animation_process_mode == ANIMATION_PROCESS_PHYSICS) - break; - - if (processing) - _process_animation(get_process_delta_time()); - } break; - case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { - - if (animation_process_mode == ANIMATION_PROCESS_IDLE) - break; - - if (processing) - _process_animation(get_physics_process_delta_time()); - } break; - } -} - -void AnimationTreePlayer::_compute_weights(float *p_fallback_weight, HashMap<NodePath, float> *p_weights, float p_coeff, const HashMap<NodePath, bool> *p_filter, float p_filtered_coeff) { - - if (p_filter != NULL) { - - List<NodePath> key_list; - p_filter->get_key_list(&key_list); - - for (List<NodePath>::Element *E = key_list.front(); E; E = E->next()) { - - if ((*p_filter)[E->get()]) { - - if (p_weights->has(E->get())) { - (*p_weights)[E->get()] *= p_filtered_coeff; - } else { - p_weights->set(E->get(), *p_fallback_weight * p_filtered_coeff); - } - - } else if (p_weights->has(E->get())) { - (*p_weights)[E->get()] *= p_coeff; - } - } - } - - List<NodePath> key_list; - p_weights->get_key_list(&key_list); - - for (List<NodePath>::Element *E = key_list.front(); E; E = E->next()) { - if (p_filter == NULL || !p_filter->has(E->get())) { - (*p_weights)[E->get()] *= p_coeff; - } - } - - *p_fallback_weight *= p_coeff; -} - -float AnimationTreePlayer::_process_node(const StringName &p_node, AnimationNode **r_prev_anim, float p_time, bool p_seek, float p_fallback_weight, HashMap<NodePath, float> *p_weights) { - - ERR_FAIL_COND_V(!node_map.has(p_node), 0); - NodeBase *nb = node_map[p_node]; - - //transform to seconds... - - switch (nb->type) { - - case NODE_OUTPUT: { - - NodeOut *on = static_cast<NodeOut *>(nb); - HashMap<NodePath, float> weights; - - return _process_node(on->inputs[0].node, r_prev_anim, p_time, p_seek, p_fallback_weight, &weights); - - } break; - case NODE_ANIMATION: { - - AnimationNode *an = static_cast<AnimationNode *>(nb); - - float rem = 0; - if (!an->animation.is_null()) { - - //float pos = an->time; - //float delta = p_time; - - //const Animation *a = an->animation.operator->(); - - if (p_seek) { - an->time = p_time; - an->step = 0; - } else { - an->time = MAX(0, an->time + p_time); - an->step = p_time; - } - - float anim_size = an->animation->get_length(); - - if (an->animation->has_loop()) { - - if (anim_size) - an->time = Math::fposmod(an->time, anim_size); - - } else if (an->time > anim_size) { - - an->time = anim_size; - } - - an->skip = true; - - for (List<AnimationNode::TrackRef>::Element *E = an->tref.front(); E; E = E->next()) { - NodePath track_path = an->animation->track_get_path(E->get().local_track); - if (an->filter.has(track_path) && an->filter[track_path]) { - E->get().weight = 0; - } else { - if (p_weights->has(track_path)) { - float weight = (*p_weights)[track_path]; - E->get().weight = weight; - } else { - E->get().weight = p_fallback_weight; - } - } - if (E->get().weight > CMP_EPSILON) - an->skip = false; - } - - rem = anim_size - an->time; - } - - if (!(*r_prev_anim)) - active_list = an; - else - (*r_prev_anim)->next = an; - - an->next = NULL; - *r_prev_anim = an; - - return rem; - - } break; - case NODE_ONESHOT: { - - OneShotNode *osn = static_cast<OneShotNode *>(nb); - - if (!osn->active) { - //make it as if this node doesn't exist, pass input 0 by. - return _process_node(osn->inputs[0].node, r_prev_anim, p_time, p_seek, p_fallback_weight, p_weights); - } - - bool os_seek = p_seek; - - if (p_seek) - osn->time = p_time; - if (osn->start) { - osn->time = 0; - os_seek = true; - } - - float blend; - - if (osn->time < osn->fade_in) { - - if (osn->fade_in > 0) - blend = osn->time / osn->fade_in; - else - blend = 0; //wtf - - } else if (!osn->start && osn->remaining < osn->fade_out) { - - if (osn->fade_out) - blend = (osn->remaining / osn->fade_out); - else - blend = 1.0; - } else - blend = 1.0; - - float main_rem; - float os_rem; - - HashMap<NodePath, float> os_weights(*p_weights); - float os_fallback_weight = p_fallback_weight; - _compute_weights(&p_fallback_weight, p_weights, osn->mix ? 1.0 : 1.0 - blend, &osn->filter, 1.0); - _compute_weights(&os_fallback_weight, &os_weights, blend, &osn->filter, 0.0); - - main_rem = _process_node(osn->inputs[0].node, r_prev_anim, p_time, p_seek, p_fallback_weight, p_weights); - os_rem = _process_node(osn->inputs[1].node, r_prev_anim, p_time, os_seek, os_fallback_weight, &os_weights); - - if (osn->start) { - osn->remaining = os_rem; - osn->start = false; - } - - if (!p_seek) { - osn->time += p_time; - osn->remaining = os_rem; - if (osn->remaining <= 0) - osn->active = false; - } - - return MAX(main_rem, osn->remaining); - } break; - case NODE_MIX: { - MixNode *mn = static_cast<MixNode *>(nb); - - HashMap<NodePath, float> mn_weights(*p_weights); - float mn_fallback_weight = p_fallback_weight; - _compute_weights(&mn_fallback_weight, &mn_weights, mn->amount); - float rem = _process_node(mn->inputs[0].node, r_prev_anim, p_time, p_seek, p_fallback_weight, p_weights); - _process_node(mn->inputs[1].node, r_prev_anim, p_time, p_seek, mn_fallback_weight, &mn_weights); - return rem; - - } break; - case NODE_BLEND2: { - - Blend2Node *bn = static_cast<Blend2Node *>(nb); - - HashMap<NodePath, float> bn_weights(*p_weights); - float bn_fallback_weight = p_fallback_weight; - _compute_weights(&p_fallback_weight, p_weights, 1.0 - bn->value, &bn->filter, 1.0); - _compute_weights(&bn_fallback_weight, &bn_weights, bn->value, &bn->filter, 0.0); - float rem = _process_node(bn->inputs[0].node, r_prev_anim, p_time, p_seek, p_fallback_weight, p_weights); - _process_node(bn->inputs[1].node, r_prev_anim, p_time, p_seek, bn_fallback_weight, &bn_weights); - - return rem; - } break; - case NODE_BLEND3: { - Blend3Node *bn = static_cast<Blend3Node *>(nb); - - float rem; - float blend, lower_blend, upper_blend; - if (bn->value < 0) { - lower_blend = -bn->value; - blend = 1.0 - lower_blend; - upper_blend = 0; - } else { - lower_blend = 0; - blend = 1.0 - bn->value; - upper_blend = bn->value; - } - - HashMap<NodePath, float> upper_weights(*p_weights); - float upper_fallback_weight = p_fallback_weight; - HashMap<NodePath, float> lower_weights(*p_weights); - float lower_fallback_weight = p_fallback_weight; - _compute_weights(&upper_fallback_weight, &upper_weights, upper_blend); - _compute_weights(&p_fallback_weight, p_weights, blend); - _compute_weights(&lower_fallback_weight, &lower_weights, lower_blend); - - rem = _process_node(bn->inputs[1].node, r_prev_anim, p_time, p_seek, p_fallback_weight, p_weights); - _process_node(bn->inputs[0].node, r_prev_anim, p_time, p_seek, lower_fallback_weight, &lower_weights); - _process_node(bn->inputs[2].node, r_prev_anim, p_time, p_seek, upper_fallback_weight, &upper_weights); - - return rem; - } break; - case NODE_BLEND4: { - Blend4Node *bn = static_cast<Blend4Node *>(nb); - - HashMap<NodePath, float> weights1(*p_weights); - float fallback_weight1 = p_fallback_weight; - HashMap<NodePath, float> weights2(*p_weights); - float fallback_weight2 = p_fallback_weight; - HashMap<NodePath, float> weights3(*p_weights); - float fallback_weight3 = p_fallback_weight; - - _compute_weights(&p_fallback_weight, p_weights, 1.0 - bn->value.x); - _compute_weights(&fallback_weight1, &weights1, bn->value.x); - _compute_weights(&fallback_weight2, &weights2, 1.0 - bn->value.y); - _compute_weights(&fallback_weight3, &weights3, bn->value.y); - - float rem = _process_node(bn->inputs[0].node, r_prev_anim, p_time, p_seek, p_fallback_weight, p_weights); - _process_node(bn->inputs[1].node, r_prev_anim, p_time, p_seek, fallback_weight1, &weights1); - float rem2 = _process_node(bn->inputs[2].node, r_prev_anim, p_time, p_seek, fallback_weight2, &weights2); - _process_node(bn->inputs[3].node, r_prev_anim, p_time, p_seek, fallback_weight3, &weights3); - - return MAX(rem, rem2); - - } break; - case NODE_TIMESCALE: { - TimeScaleNode *tsn = static_cast<TimeScaleNode *>(nb); - float rem; - if (p_seek) - rem = _process_node(tsn->inputs[0].node, r_prev_anim, p_time, true, p_fallback_weight, p_weights); - else - rem = _process_node(tsn->inputs[0].node, r_prev_anim, p_time * tsn->scale, false, p_fallback_weight, p_weights); - if (tsn->scale == 0) - return Math_INF; - else - return rem / tsn->scale; - - } break; - case NODE_TIMESEEK: { - - TimeSeekNode *tsn = static_cast<TimeSeekNode *>(nb); - if (tsn->seek_pos >= 0 && !p_seek) { - - p_time = tsn->seek_pos; - p_seek = true; - } - tsn->seek_pos = -1; - - return _process_node(tsn->inputs[0].node, r_prev_anim, p_time, p_seek, p_fallback_weight, p_weights); - - } break; - case NODE_TRANSITION: { - - TransitionNode *tn = static_cast<TransitionNode *>(nb); - HashMap<NodePath, float> prev_weights(*p_weights); - float prev_fallback_weight = p_fallback_weight; - - if (tn->prev < 0) { // process current animation, check for transition - - float rem = _process_node(tn->inputs[tn->current].node, r_prev_anim, p_time, p_seek, p_fallback_weight, p_weights); - if (p_seek) - tn->time = p_time; - else - tn->time += p_time; - - if (tn->input_data[tn->current].auto_advance && rem <= tn->xfade) { - - tn->set_current((tn->current + 1) % tn->inputs.size()); - } - - return rem; - } else { // cross-fading from tn->prev to tn->current - - float blend = tn->xfade ? (tn->prev_xfading / tn->xfade) : 1; - - float rem; - - _compute_weights(&p_fallback_weight, p_weights, 1.0 - blend); - _compute_weights(&prev_fallback_weight, &prev_weights, blend); - - if (!p_seek && tn->switched) { //just switched, seek to start of current - - rem = _process_node(tn->inputs[tn->current].node, r_prev_anim, 0, true, p_fallback_weight, p_weights); - } else { - - rem = _process_node(tn->inputs[tn->current].node, r_prev_anim, p_time, p_seek, p_fallback_weight, p_weights); - } - - tn->switched = false; - - if (p_seek) { // don't seek prev animation - _process_node(tn->inputs[tn->prev].node, r_prev_anim, 0, false, prev_fallback_weight, &prev_weights); - tn->time = p_time; - } else { - _process_node(tn->inputs[tn->prev].node, r_prev_anim, p_time, false, prev_fallback_weight, &prev_weights); - tn->time += p_time; - tn->prev_xfading -= p_time; - if (tn->prev_xfading < 0) { - - tn->prev = -1; - } - } - - return rem; - } - - } break; - default: { - } - } - - return 0; -} - -void AnimationTreePlayer::_process_animation(float p_delta) { - - if (last_error != CONNECT_OK) - return; - - if (dirty_caches) - _recompute_caches(); - - active_list = NULL; - AnimationNode *prev = NULL; - - if (reset_request) { - - _process_node(out_name, &prev, 0, true); - reset_request = false; - } else - _process_node(out_name, &prev, p_delta); - - if (dirty_caches) { - //some animation changed.. ignore this pass - return; - } - - //update the tracks.. - - /* STEP 1 CLEAR TRACKS */ - - for (TrackMap::Element *E = track_map.front(); E; E = E->next()) { - - Track &t = E->get(); - - t.loc.zero(); - t.rot = Quat(); - t.scale.x = 0; - t.scale.y = 0; - t.scale.z = 0; - - t.value = t.object->get_indexed(t.subpath); - t.value.zero(); - - t.skip = false; - } - - /* STEP 2 PROCESS ANIMATIONS */ - - AnimationNode *anim_list = active_list; - Quat empty_rot; - - while (anim_list) { - - if (!anim_list->animation.is_null() && !anim_list->skip) { - //check if animation is meaningful - Animation *a = anim_list->animation.operator->(); - - for (List<AnimationNode::TrackRef>::Element *E = anim_list->tref.front(); E; E = E->next()) { - - AnimationNode::TrackRef &tr = E->get(); - if (tr.track == NULL || tr.local_track < 0 || tr.weight < CMP_EPSILON || !a->track_is_enabled(tr.local_track)) - continue; - - switch (a->track_get_type(tr.local_track)) { - case Animation::TYPE_TRANSFORM: { ///< Transform a node or a bone. - - Vector3 loc; - Quat rot; - Vector3 scale; - a->transform_track_interpolate(tr.local_track, anim_list->time, &loc, &rot, &scale); - - tr.track->loc += loc * tr.weight; - - scale.x -= 1.0; - scale.y -= 1.0; - scale.z -= 1.0; - tr.track->scale += scale * tr.weight; - - tr.track->rot = tr.track->rot * empty_rot.slerp(rot, tr.weight); - - } break; - case Animation::TYPE_VALUE: { ///< Set a value in a property, can be interpolated. - - if (a->value_track_get_update_mode(tr.local_track) == Animation::UPDATE_CONTINUOUS) { - Variant value = a->value_track_interpolate(tr.local_track, anim_list->time); - Variant::blend(tr.track->value, value, tr.weight, tr.track->value); - } else { - int index = a->track_find_key(tr.local_track, anim_list->time); - tr.track->value = a->track_get_key_value(tr.local_track, index); - } - } break; - case Animation::TYPE_METHOD: { ///< Call any method on a specific node. - - List<int> indices; - a->method_track_get_key_indices(tr.local_track, anim_list->time, anim_list->step, &indices); - for (List<int>::Element *F = indices.front(); F; F = F->next()) { - - StringName method = a->method_track_get_name(tr.local_track, F->get()); - Vector<Variant> args = a->method_track_get_params(tr.local_track, F->get()); - args.resize(VARIANT_ARG_MAX); - tr.track->object->call(method, args[0], args[1], args[2], args[3], args[4]); - } - } break; - default: { - } - } - } - } - - anim_list = anim_list->next; - } - - /* STEP 3 APPLY TRACKS */ - - for (TrackMap::Element *E = track_map.front(); E; E = E->next()) { - - Track &t = E->get(); - - if (t.skip || !t.object) - continue; - - if (t.subpath.size()) { // value track - t.object->set_indexed(t.subpath, t.value); - continue; - } - - Transform xform; - xform.origin = t.loc; - - t.scale.x += 1.0; - t.scale.y += 1.0; - t.scale.z += 1.0; - xform.basis.set_quat_scale(t.rot, t.scale); - - if (t.bone_idx >= 0) { - if (t.skeleton) - t.skeleton->set_bone_pose(t.bone_idx, xform); - - } else if (t.spatial) { - - t.spatial->set_transform(xform); - } - } -} - -void AnimationTreePlayer::add_node(NodeType p_type, const StringName &p_node) { - - ERR_FAIL_COND(p_type == NODE_OUTPUT); - ERR_FAIL_COND(node_map.has(p_node)); - - NodeBase *n = NULL; - - switch (p_type) { - - case NODE_ANIMATION: { - - n = memnew(AnimationNode); - } break; - case NODE_ONESHOT: { - - n = memnew(OneShotNode); - - } break; - case NODE_MIX: { - n = memnew(MixNode); - - } break; - case NODE_BLEND2: { - n = memnew(Blend2Node); - - } break; - case NODE_BLEND3: { - n = memnew(Blend3Node); - - } break; - case NODE_BLEND4: { - n = memnew(Blend4Node); - - } break; - case NODE_TIMESCALE: { - n = memnew(TimeScaleNode); - - } break; - case NODE_TIMESEEK: { - n = memnew(TimeSeekNode); - - } break; - case NODE_TRANSITION: { - n = memnew(TransitionNode); - - } break; - default: { - } - } - - //n->name+=" "+itos(p_node); - node_map[p_node] = n; -} - -StringName AnimationTreePlayer::node_get_input_source(const StringName &p_node, int p_input) const { - - ERR_FAIL_COND_V(!node_map.has(p_node), StringName()); - ERR_FAIL_INDEX_V(p_input, node_map[p_node]->inputs.size(), StringName()); - return node_map[p_node]->inputs[p_input].node; -} - -int AnimationTreePlayer::node_get_input_count(const StringName &p_node) const { - - ERR_FAIL_COND_V(!node_map.has(p_node), -1); - return node_map[p_node]->inputs.size(); -} -#define GET_NODE(m_type, m_cast) \ - ERR_FAIL_COND(!node_map.has(p_node)); \ - ERR_FAIL_COND_MSG(node_map[p_node]->type != m_type, "Invalid parameter for node type."); \ - m_cast *n = static_cast<m_cast *>(node_map[p_node]); - -void AnimationTreePlayer::animation_node_set_animation(const StringName &p_node, const Ref<Animation> &p_animation) { - - GET_NODE(NODE_ANIMATION, AnimationNode); - n->animation = p_animation; - dirty_caches = true; -} - -void AnimationTreePlayer::animation_node_set_master_animation(const StringName &p_node, const String &p_master_animation) { - - GET_NODE(NODE_ANIMATION, AnimationNode); - n->from = p_master_animation; - dirty_caches = true; - if (master != NodePath()) - _update_sources(); -} - -void AnimationTreePlayer::animation_node_set_filter_path(const StringName &p_node, const NodePath &p_track_path, bool p_filter) { - - GET_NODE(NODE_ANIMATION, AnimationNode); - - if (p_filter) - n->filter[p_track_path] = true; - else - n->filter.erase(p_track_path); -} - -void AnimationTreePlayer::animation_node_set_get_filtered_paths(const StringName &p_node, List<NodePath> *r_paths) const { - - GET_NODE(NODE_ANIMATION, AnimationNode); - - n->filter.get_key_list(r_paths); -} - -void AnimationTreePlayer::oneshot_node_set_fadein_time(const StringName &p_node, float p_time) { - - GET_NODE(NODE_ONESHOT, OneShotNode); - n->fade_in = p_time; -} - -void AnimationTreePlayer::oneshot_node_set_fadeout_time(const StringName &p_node, float p_time) { - - GET_NODE(NODE_ONESHOT, OneShotNode); - n->fade_out = p_time; -} - -void AnimationTreePlayer::oneshot_node_set_mix_mode(const StringName &p_node, bool p_mix) { - - GET_NODE(NODE_ONESHOT, OneShotNode); - n->mix = p_mix; -} - -void AnimationTreePlayer::oneshot_node_set_autorestart(const StringName &p_node, bool p_active) { - - GET_NODE(NODE_ONESHOT, OneShotNode); - n->autorestart = p_active; -} - -void AnimationTreePlayer::oneshot_node_set_autorestart_delay(const StringName &p_node, float p_time) { - - GET_NODE(NODE_ONESHOT, OneShotNode); - n->autorestart_delay = p_time; -} -void AnimationTreePlayer::oneshot_node_set_autorestart_random_delay(const StringName &p_node, float p_time) { - - GET_NODE(NODE_ONESHOT, OneShotNode); - n->autorestart_random_delay = p_time; -} - -void AnimationTreePlayer::oneshot_node_start(const StringName &p_node) { - - GET_NODE(NODE_ONESHOT, OneShotNode); - n->active = true; - n->start = true; -} - -void AnimationTreePlayer::oneshot_node_stop(const StringName &p_node) { - - GET_NODE(NODE_ONESHOT, OneShotNode); - n->active = false; -} - -void AnimationTreePlayer::oneshot_node_set_filter_path(const StringName &p_node, const NodePath &p_filter, bool p_enable) { - - GET_NODE(NODE_ONESHOT, OneShotNode); - - if (p_enable) - n->filter[p_filter] = true; - else - n->filter.erase(p_filter); -} - -void AnimationTreePlayer::oneshot_node_set_get_filtered_paths(const StringName &p_node, List<NodePath> *r_paths) const { - - GET_NODE(NODE_ONESHOT, OneShotNode); - - n->filter.get_key_list(r_paths); -} - -void AnimationTreePlayer::mix_node_set_amount(const StringName &p_node, float p_amount) { - - GET_NODE(NODE_MIX, MixNode); - n->amount = p_amount; -} - -void AnimationTreePlayer::blend2_node_set_amount(const StringName &p_node, float p_amount) { - - GET_NODE(NODE_BLEND2, Blend2Node); - n->value = p_amount; -} - -void AnimationTreePlayer::blend2_node_set_filter_path(const StringName &p_node, const NodePath &p_filter, bool p_enable) { - - GET_NODE(NODE_BLEND2, Blend2Node); - - if (p_enable) - n->filter[p_filter] = true; - else - n->filter.erase(p_filter); -} - -void AnimationTreePlayer::blend2_node_set_get_filtered_paths(const StringName &p_node, List<NodePath> *r_paths) const { - - GET_NODE(NODE_BLEND2, Blend2Node); - - n->filter.get_key_list(r_paths); -} - -void AnimationTreePlayer::blend3_node_set_amount(const StringName &p_node, float p_amount) { - - GET_NODE(NODE_BLEND3, Blend3Node); - n->value = p_amount; -} -void AnimationTreePlayer::blend4_node_set_amount(const StringName &p_node, const Vector2 &p_amount) { - - GET_NODE(NODE_BLEND4, Blend4Node); - n->value = p_amount; -} -void AnimationTreePlayer::timescale_node_set_scale(const StringName &p_node, float p_scale) { - - GET_NODE(NODE_TIMESCALE, TimeScaleNode); - n->scale = p_scale; -} -void AnimationTreePlayer::timeseek_node_seek(const StringName &p_node, float p_pos) { - - GET_NODE(NODE_TIMESEEK, TimeSeekNode); - n->seek_pos = p_pos; -} -void AnimationTreePlayer::transition_node_set_input_count(const StringName &p_node, int p_inputs) { - - GET_NODE(NODE_TRANSITION, TransitionNode); - ERR_FAIL_COND(p_inputs < 1); - - n->inputs.resize(p_inputs); - n->input_data.resize(p_inputs); - - _clear_cycle_test(); - - last_error = _cycle_test(out_name); -} -void AnimationTreePlayer::transition_node_set_input_auto_advance(const StringName &p_node, int p_input, bool p_auto_advance) { - - GET_NODE(NODE_TRANSITION, TransitionNode); - ERR_FAIL_INDEX(p_input, n->input_data.size()); - - n->input_data.write[p_input].auto_advance = p_auto_advance; -} -void AnimationTreePlayer::transition_node_set_xfade_time(const StringName &p_node, float p_time) { - - GET_NODE(NODE_TRANSITION, TransitionNode); - n->xfade = p_time; -} - -void AnimationTreePlayer::TransitionNode::set_current(int p_current) { - - ERR_FAIL_INDEX(p_current, inputs.size()); - - if (current == p_current) - return; - - prev = current; - prev_xfading = xfade; - prev_time = time; - time = 0; - current = p_current; - switched = true; -} - -void AnimationTreePlayer::transition_node_set_current(const StringName &p_node, int p_current) { - - GET_NODE(NODE_TRANSITION, TransitionNode); - n->set_current(p_current); -} - -void AnimationTreePlayer::node_set_position(const StringName &p_node, const Vector2 &p_pos) { - - ERR_FAIL_COND(!node_map.has(p_node)); - node_map[p_node]->pos = p_pos; -} - -AnimationTreePlayer::NodeType AnimationTreePlayer::node_get_type(const StringName &p_node) const { - - ERR_FAIL_COND_V(!node_map.has(p_node), NODE_OUTPUT); - return node_map[p_node]->type; -} -Point2 AnimationTreePlayer::node_get_position(const StringName &p_node) const { - - ERR_FAIL_COND_V(!node_map.has(p_node), Point2()); - return node_map[p_node]->pos; -} - -#define GET_NODE_V(m_type, m_cast, m_ret) \ - ERR_FAIL_COND_V(!node_map.has(p_node), m_ret); \ - ERR_FAIL_COND_V_MSG(node_map[p_node]->type != m_type, m_ret, "Invalid parameter for node type."); \ - m_cast *n = static_cast<m_cast *>(node_map[p_node]); - -Ref<Animation> AnimationTreePlayer::animation_node_get_animation(const StringName &p_node) const { - - GET_NODE_V(NODE_ANIMATION, AnimationNode, Ref<Animation>()); - return n->animation; -} - -String AnimationTreePlayer::animation_node_get_master_animation(const StringName &p_node) const { - - GET_NODE_V(NODE_ANIMATION, AnimationNode, String()); - return n->from; -} - -float AnimationTreePlayer::animation_node_get_position(const StringName &p_node) const { - - GET_NODE_V(NODE_ANIMATION, AnimationNode, 0); - return n->time; -} - -bool AnimationTreePlayer::animation_node_is_path_filtered(const StringName &p_node, const NodePath &p_path) const { - - GET_NODE_V(NODE_ANIMATION, AnimationNode, 0); - return n->filter.has(p_path); -} - -float AnimationTreePlayer::oneshot_node_get_fadein_time(const StringName &p_node) const { - - GET_NODE_V(NODE_ONESHOT, OneShotNode, 0); - return n->fade_in; -} - -float AnimationTreePlayer::oneshot_node_get_fadeout_time(const StringName &p_node) const { - - GET_NODE_V(NODE_ONESHOT, OneShotNode, 0); - return n->fade_out; -} - -bool AnimationTreePlayer::oneshot_node_get_mix_mode(const StringName &p_node) const { - - GET_NODE_V(NODE_ONESHOT, OneShotNode, 0); - return n->mix; -} -bool AnimationTreePlayer::oneshot_node_has_autorestart(const StringName &p_node) const { - - GET_NODE_V(NODE_ONESHOT, OneShotNode, 0); - return n->autorestart; -} -float AnimationTreePlayer::oneshot_node_get_autorestart_delay(const StringName &p_node) const { - - GET_NODE_V(NODE_ONESHOT, OneShotNode, 0); - return n->autorestart_delay; -} -float AnimationTreePlayer::oneshot_node_get_autorestart_random_delay(const StringName &p_node) const { - - GET_NODE_V(NODE_ONESHOT, OneShotNode, 0); - return n->autorestart_random_delay; -} - -bool AnimationTreePlayer::oneshot_node_is_active(const StringName &p_node) const { - - GET_NODE_V(NODE_ONESHOT, OneShotNode, 0); - return n->active; -} - -bool AnimationTreePlayer::oneshot_node_is_path_filtered(const StringName &p_node, const NodePath &p_path) const { - - GET_NODE_V(NODE_ONESHOT, OneShotNode, 0); - return n->filter.has(p_path); -} - -float AnimationTreePlayer::mix_node_get_amount(const StringName &p_node) const { - - GET_NODE_V(NODE_MIX, MixNode, 0); - return n->amount; -} -float AnimationTreePlayer::blend2_node_get_amount(const StringName &p_node) const { - - GET_NODE_V(NODE_BLEND2, Blend2Node, 0); - return n->value; -} - -bool AnimationTreePlayer::blend2_node_is_path_filtered(const StringName &p_node, const NodePath &p_path) const { - - GET_NODE_V(NODE_BLEND2, Blend2Node, 0); - return n->filter.has(p_path); -} - -float AnimationTreePlayer::blend3_node_get_amount(const StringName &p_node) const { - - GET_NODE_V(NODE_BLEND3, Blend3Node, 0); - return n->value; -} -Vector2 AnimationTreePlayer::blend4_node_get_amount(const StringName &p_node) const { - - GET_NODE_V(NODE_BLEND4, Blend4Node, Vector2()); - return n->value; -} - -float AnimationTreePlayer::timescale_node_get_scale(const StringName &p_node) const { - - GET_NODE_V(NODE_TIMESCALE, TimeScaleNode, 0); - return n->scale; -} - -void AnimationTreePlayer::transition_node_delete_input(const StringName &p_node, int p_input) { - - GET_NODE(NODE_TRANSITION, TransitionNode); - ERR_FAIL_INDEX(p_input, n->inputs.size()); - - if (n->inputs.size() <= 1) - return; - - n->inputs.remove(p_input); - n->input_data.remove(p_input); - last_error = _cycle_test(out_name); -} - -int AnimationTreePlayer::transition_node_get_input_count(const StringName &p_node) const { - - GET_NODE_V(NODE_TRANSITION, TransitionNode, 0); - return n->inputs.size(); -} - -bool AnimationTreePlayer::transition_node_has_input_auto_advance(const StringName &p_node, int p_input) const { - - GET_NODE_V(NODE_TRANSITION, TransitionNode, false); - ERR_FAIL_INDEX_V(p_input, n->inputs.size(), false); - return n->input_data[p_input].auto_advance; -} -float AnimationTreePlayer::transition_node_get_xfade_time(const StringName &p_node) const { - - GET_NODE_V(NODE_TRANSITION, TransitionNode, 0); - return n->xfade; -} - -int AnimationTreePlayer::transition_node_get_current(const StringName &p_node) const { - - GET_NODE_V(NODE_TRANSITION, TransitionNode, -1); - return n->current; -} - -/*misc */ -void AnimationTreePlayer::get_node_list(List<StringName> *p_node_list) const { - - for (Map<StringName, NodeBase *>::Element *E = node_map.front(); E; E = E->next()) { - - p_node_list->push_back(E->key()); - } -} - -void AnimationTreePlayer::remove_node(const StringName &p_node) { - - ERR_FAIL_COND(!node_map.has(p_node)); - ERR_FAIL_COND_MSG(p_node == out_name, "Node 0 (output) can't be removed."); - - for (Map<StringName, NodeBase *>::Element *E = node_map.front(); E; E = E->next()) { - - NodeBase *nb = E->get(); - for (int i = 0; i < nb->inputs.size(); i++) { - - if (nb->inputs[i].node == p_node) - nb->inputs.write[i].node = StringName(); - } - } - - node_map.erase(p_node); - - _clear_cycle_test(); - - // compute last error again, just in case - last_error = _cycle_test(out_name); - dirty_caches = true; -} - -AnimationTreePlayer::ConnectError AnimationTreePlayer::_cycle_test(const StringName &p_at_node) { - - ERR_FAIL_COND_V(!node_map.has(p_at_node), CONNECT_INCOMPLETE); - - NodeBase *nb = node_map[p_at_node]; - if (nb->cycletest) - return CONNECT_CYCLE; - - nb->cycletest = true; - - for (int i = 0; i < nb->inputs.size(); i++) { - if (nb->inputs[i].node == StringName()) - return CONNECT_INCOMPLETE; - - ConnectError _err = _cycle_test(nb->inputs[i].node); - if (_err) - return _err; - } - - return CONNECT_OK; -} - -// Use this function to not alter next complete _cycle_test(). -void AnimationTreePlayer::_clear_cycle_test() { - for (Map<StringName, NodeBase *>::Element *E = node_map.front(); E; E = E->next()) { - NodeBase *nb = E->get(); - nb->cycletest = false; - } -} - -Error AnimationTreePlayer::connect_nodes(const StringName &p_src_node, const StringName &p_dst_node, int p_dst_input) { - - ERR_FAIL_COND_V(!node_map.has(p_src_node), ERR_INVALID_PARAMETER); - ERR_FAIL_COND_V(!node_map.has(p_dst_node), ERR_INVALID_PARAMETER); - ERR_FAIL_COND_V(p_src_node == p_dst_node, ERR_INVALID_PARAMETER); - - //NodeBase *src = node_map[p_src_node]; - NodeBase *dst = node_map[p_dst_node]; - ERR_FAIL_INDEX_V(p_dst_input, dst->inputs.size(), ERR_INVALID_PARAMETER); - - //int oldval = dst->inputs[p_dst_input].node; - - for (Map<StringName, NodeBase *>::Element *E = node_map.front(); E; E = E->next()) { - - NodeBase *nb = E->get(); - for (int i = 0; i < nb->inputs.size(); i++) { - - if (nb->inputs[i].node == p_src_node) - nb->inputs.write[i].node = StringName(); - } - } - - dst->inputs.write[p_dst_input].node = p_src_node; - - _clear_cycle_test(); - - last_error = _cycle_test(out_name); - if (last_error) { - - if (last_error == CONNECT_INCOMPLETE) - return ERR_UNCONFIGURED; - else if (last_error == CONNECT_CYCLE) - return ERR_CYCLIC_LINK; - } - dirty_caches = true; - return OK; -} - -bool AnimationTreePlayer::are_nodes_connected(const StringName &p_src_node, const StringName &p_dst_node, int p_dst_input) const { - - ERR_FAIL_COND_V(!node_map.has(p_src_node), false); - ERR_FAIL_COND_V(!node_map.has(p_dst_node), false); - ERR_FAIL_COND_V(p_src_node == p_dst_node, false); - - NodeBase *dst = node_map[p_dst_node]; - - return dst->inputs[p_dst_input].node == p_src_node; -} - -void AnimationTreePlayer::disconnect_nodes(const StringName &p_node, int p_input) { - - ERR_FAIL_COND(!node_map.has(p_node)); - - NodeBase *dst = node_map[p_node]; - ERR_FAIL_INDEX(p_input, dst->inputs.size()); - dst->inputs.write[p_input].node = StringName(); - last_error = CONNECT_INCOMPLETE; - dirty_caches = true; -} - -void AnimationTreePlayer::get_connection_list(List<Connection> *p_connections) const { - - for (Map<StringName, NodeBase *>::Element *E = node_map.front(); E; E = E->next()) { - - NodeBase *nb = E->get(); - for (int i = 0; i < nb->inputs.size(); i++) { - - if (nb->inputs[i].node != StringName()) { - Connection c; - c.src_node = nb->inputs[i].node; - c.dst_node = E->key(); - c.dst_input = i; - p_connections->push_back(c); - } - } - } -} - -AnimationTreePlayer::Track *AnimationTreePlayer::_find_track(const NodePath &p_path) { - - Node *parent = get_node(base_path); - ERR_FAIL_COND_V(!parent, NULL); - - RES resource; - Vector<StringName> leftover_path; - Node *child = parent->get_node_and_resource(p_path, resource, leftover_path); - if (!child) { - String err = "Animation track references unknown Node: '" + String(p_path) + "'."; - WARN_PRINT(err.ascii().get_data()); - return NULL; - } - - ObjectID id = child->get_instance_id(); - int bone_idx = -1; - - if (p_path.get_subname_count()) { - - if (Object::cast_to<Skeleton>(child)) - bone_idx = Object::cast_to<Skeleton>(child)->find_bone(p_path.get_subname(0)); - } - - TrackKey key; - key.id = id; - key.bone_idx = bone_idx; - key.subpath_concatenated = p_path.get_concatenated_subnames(); - - if (!track_map.has(key)) { - - Track tr; - tr.id = id; - tr.object = resource.is_valid() ? (Object *)resource.ptr() : (Object *)child; - tr.skeleton = Object::cast_to<Skeleton>(child); - tr.spatial = Object::cast_to<Spatial>(child); - tr.bone_idx = bone_idx; - if (bone_idx == -1) tr.subpath = leftover_path; - - track_map[key] = tr; - } - - return &track_map[key]; -} - -void AnimationTreePlayer::_recompute_caches() { - - track_map.clear(); - _recompute_caches(out_name); - dirty_caches = false; -} - -void AnimationTreePlayer::_recompute_caches(const StringName &p_node) { - - ERR_FAIL_COND(!node_map.has(p_node)); - - NodeBase *nb = node_map[p_node]; - - if (nb->type == NODE_ANIMATION) { - - AnimationNode *an = static_cast<AnimationNode *>(nb); - an->tref.clear(); - - if (!an->animation.is_null()) { - - Ref<Animation> a = an->animation; - - for (int i = 0; i < an->animation->get_track_count(); i++) { - - Track *tr = _find_track(a->track_get_path(i)); - if (!tr) - continue; - - AnimationNode::TrackRef tref; - tref.local_track = i; - tref.track = tr; - tref.weight = 0; - - an->tref.push_back(tref); - } - } - } - - for (int i = 0; i < nb->inputs.size(); i++) { - - _recompute_caches(nb->inputs[i].node); - } -} - -void AnimationTreePlayer::recompute_caches() { - - dirty_caches = true; -} - -/* playback */ - -void AnimationTreePlayer::set_active(bool p_active) { - - if (active == p_active) - return; - - active = p_active; - processing = active; - reset_request = p_active; - _set_process(processing, true); -} - -bool AnimationTreePlayer::is_active() const { - - return active; -} - -AnimationTreePlayer::ConnectError AnimationTreePlayer::get_last_error() const { - - return last_error; -} - -void AnimationTreePlayer::reset() { - - reset_request = true; -} - -void AnimationTreePlayer::set_base_path(const NodePath &p_path) { - - base_path = p_path; - recompute_caches(); -} - -NodePath AnimationTreePlayer::get_base_path() const { - - return base_path; -} - -void AnimationTreePlayer::set_master_player(const NodePath &p_path) { - - if (p_path == master) - return; - - master = p_path; - _update_sources(); - recompute_caches(); -} - -NodePath AnimationTreePlayer::get_master_player() const { - - return master; -} - -PoolVector<String> AnimationTreePlayer::_get_node_list() { - - List<StringName> nl; - get_node_list(&nl); - PoolVector<String> ret; - ret.resize(nl.size()); - int idx = 0; - for (List<StringName>::Element *E = nl.front(); E; E = E->next()) { - ret.set(idx++, E->get()); - } - - return ret; -} - -void AnimationTreePlayer::_update_sources() { - - if (master == NodePath()) - return; - if (!is_inside_tree()) - return; - - Node *m = get_node(master); - if (!m) { - master = NodePath(); - ERR_FAIL_COND(!m); - } - - AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(m); - - if (!ap) { - - master = NodePath(); - ERR_FAIL_COND(!ap); - } - - for (Map<StringName, NodeBase *>::Element *E = node_map.front(); E; E = E->next()) { - - if (E->get()->type == NODE_ANIMATION) { - - AnimationNode *an = static_cast<AnimationNode *>(E->get()); - - if (an->from != "") { - - an->animation = ap->get_animation(an->from); - } - } - } -} - -bool AnimationTreePlayer::node_exists(const StringName &p_name) const { - - return (node_map.has(p_name)); -} - -Error AnimationTreePlayer::node_rename(const StringName &p_node, const StringName &p_new_name) { - - if (p_new_name == p_node) - return OK; - ERR_FAIL_COND_V(!node_map.has(p_node), ERR_ALREADY_EXISTS); - ERR_FAIL_COND_V(node_map.has(p_new_name), ERR_ALREADY_EXISTS); - ERR_FAIL_COND_V(p_new_name == StringName(), ERR_INVALID_DATA); - ERR_FAIL_COND_V(p_node == out_name, ERR_INVALID_DATA); - ERR_FAIL_COND_V(p_new_name == out_name, ERR_INVALID_DATA); - - for (Map<StringName, NodeBase *>::Element *E = node_map.front(); E; E = E->next()) { - - NodeBase *nb = E->get(); - for (int i = 0; i < nb->inputs.size(); i++) { - - if (nb->inputs[i].node == p_node) { - nb->inputs.write[i].node = p_new_name; - } - } - } - - node_map[p_new_name] = node_map[p_node]; - node_map.erase(p_node); - - return OK; -} - -String AnimationTreePlayer::get_configuration_warning() const { - - return TTR("This node has been deprecated. Use AnimationTree instead."); -} - -void AnimationTreePlayer::_bind_methods() { - - ClassDB::bind_method(D_METHOD("add_node", "type", "id"), &AnimationTreePlayer::add_node); - - ClassDB::bind_method(D_METHOD("node_exists", "node"), &AnimationTreePlayer::node_exists); - ClassDB::bind_method(D_METHOD("node_rename", "node", "new_name"), &AnimationTreePlayer::node_rename); - - ClassDB::bind_method(D_METHOD("node_get_type", "id"), &AnimationTreePlayer::node_get_type); - ClassDB::bind_method(D_METHOD("node_get_input_count", "id"), &AnimationTreePlayer::node_get_input_count); - ClassDB::bind_method(D_METHOD("node_get_input_source", "id", "idx"), &AnimationTreePlayer::node_get_input_source); - - ClassDB::bind_method(D_METHOD("animation_node_set_animation", "id", "animation"), &AnimationTreePlayer::animation_node_set_animation); - ClassDB::bind_method(D_METHOD("animation_node_get_animation", "id"), &AnimationTreePlayer::animation_node_get_animation); - - ClassDB::bind_method(D_METHOD("animation_node_set_master_animation", "id", "source"), &AnimationTreePlayer::animation_node_set_master_animation); - ClassDB::bind_method(D_METHOD("animation_node_get_master_animation", "id"), &AnimationTreePlayer::animation_node_get_master_animation); - ClassDB::bind_method(D_METHOD("animation_node_get_position", "id"), &AnimationTreePlayer::animation_node_get_position); - ClassDB::bind_method(D_METHOD("animation_node_set_filter_path", "id", "path", "enable"), &AnimationTreePlayer::animation_node_set_filter_path); - - ClassDB::bind_method(D_METHOD("oneshot_node_set_fadein_time", "id", "time_sec"), &AnimationTreePlayer::oneshot_node_set_fadein_time); - ClassDB::bind_method(D_METHOD("oneshot_node_get_fadein_time", "id"), &AnimationTreePlayer::oneshot_node_get_fadein_time); - - ClassDB::bind_method(D_METHOD("oneshot_node_set_fadeout_time", "id", "time_sec"), &AnimationTreePlayer::oneshot_node_set_fadeout_time); - ClassDB::bind_method(D_METHOD("oneshot_node_get_fadeout_time", "id"), &AnimationTreePlayer::oneshot_node_get_fadeout_time); - - ClassDB::bind_method(D_METHOD("oneshot_node_set_autorestart", "id", "enable"), &AnimationTreePlayer::oneshot_node_set_autorestart); - ClassDB::bind_method(D_METHOD("oneshot_node_set_autorestart_delay", "id", "delay_sec"), &AnimationTreePlayer::oneshot_node_set_autorestart_delay); - ClassDB::bind_method(D_METHOD("oneshot_node_set_autorestart_random_delay", "id", "rand_sec"), &AnimationTreePlayer::oneshot_node_set_autorestart_random_delay); - - ClassDB::bind_method(D_METHOD("oneshot_node_has_autorestart", "id"), &AnimationTreePlayer::oneshot_node_has_autorestart); - ClassDB::bind_method(D_METHOD("oneshot_node_get_autorestart_delay", "id"), &AnimationTreePlayer::oneshot_node_get_autorestart_delay); - ClassDB::bind_method(D_METHOD("oneshot_node_get_autorestart_random_delay", "id"), &AnimationTreePlayer::oneshot_node_get_autorestart_random_delay); - - ClassDB::bind_method(D_METHOD("oneshot_node_start", "id"), &AnimationTreePlayer::oneshot_node_start); - ClassDB::bind_method(D_METHOD("oneshot_node_stop", "id"), &AnimationTreePlayer::oneshot_node_stop); - ClassDB::bind_method(D_METHOD("oneshot_node_is_active", "id"), &AnimationTreePlayer::oneshot_node_is_active); - ClassDB::bind_method(D_METHOD("oneshot_node_set_filter_path", "id", "path", "enable"), &AnimationTreePlayer::oneshot_node_set_filter_path); - - ClassDB::bind_method(D_METHOD("mix_node_set_amount", "id", "ratio"), &AnimationTreePlayer::mix_node_set_amount); - ClassDB::bind_method(D_METHOD("mix_node_get_amount", "id"), &AnimationTreePlayer::mix_node_get_amount); - - ClassDB::bind_method(D_METHOD("blend2_node_set_amount", "id", "blend"), &AnimationTreePlayer::blend2_node_set_amount); - ClassDB::bind_method(D_METHOD("blend2_node_get_amount", "id"), &AnimationTreePlayer::blend2_node_get_amount); - ClassDB::bind_method(D_METHOD("blend2_node_set_filter_path", "id", "path", "enable"), &AnimationTreePlayer::blend2_node_set_filter_path); - - ClassDB::bind_method(D_METHOD("blend3_node_set_amount", "id", "blend"), &AnimationTreePlayer::blend3_node_set_amount); - ClassDB::bind_method(D_METHOD("blend3_node_get_amount", "id"), &AnimationTreePlayer::blend3_node_get_amount); - - ClassDB::bind_method(D_METHOD("blend4_node_set_amount", "id", "blend"), &AnimationTreePlayer::blend4_node_set_amount); - ClassDB::bind_method(D_METHOD("blend4_node_get_amount", "id"), &AnimationTreePlayer::blend4_node_get_amount); - - ClassDB::bind_method(D_METHOD("timescale_node_set_scale", "id", "scale"), &AnimationTreePlayer::timescale_node_set_scale); - ClassDB::bind_method(D_METHOD("timescale_node_get_scale", "id"), &AnimationTreePlayer::timescale_node_get_scale); - - ClassDB::bind_method(D_METHOD("timeseek_node_seek", "id", "seconds"), &AnimationTreePlayer::timeseek_node_seek); - - ClassDB::bind_method(D_METHOD("transition_node_set_input_count", "id", "count"), &AnimationTreePlayer::transition_node_set_input_count); - ClassDB::bind_method(D_METHOD("transition_node_get_input_count", "id"), &AnimationTreePlayer::transition_node_get_input_count); - ClassDB::bind_method(D_METHOD("transition_node_delete_input", "id", "input_idx"), &AnimationTreePlayer::transition_node_delete_input); - - ClassDB::bind_method(D_METHOD("transition_node_set_input_auto_advance", "id", "input_idx", "enable"), &AnimationTreePlayer::transition_node_set_input_auto_advance); - ClassDB::bind_method(D_METHOD("transition_node_has_input_auto_advance", "id", "input_idx"), &AnimationTreePlayer::transition_node_has_input_auto_advance); - - ClassDB::bind_method(D_METHOD("transition_node_set_xfade_time", "id", "time_sec"), &AnimationTreePlayer::transition_node_set_xfade_time); - ClassDB::bind_method(D_METHOD("transition_node_get_xfade_time", "id"), &AnimationTreePlayer::transition_node_get_xfade_time); - - ClassDB::bind_method(D_METHOD("transition_node_set_current", "id", "input_idx"), &AnimationTreePlayer::transition_node_set_current); - ClassDB::bind_method(D_METHOD("transition_node_get_current", "id"), &AnimationTreePlayer::transition_node_get_current); - - ClassDB::bind_method(D_METHOD("node_set_position", "id", "screen_position"), &AnimationTreePlayer::node_set_position); - ClassDB::bind_method(D_METHOD("node_get_position", "id"), &AnimationTreePlayer::node_get_position); - - ClassDB::bind_method(D_METHOD("remove_node", "id"), &AnimationTreePlayer::remove_node); - ClassDB::bind_method(D_METHOD("connect_nodes", "id", "dst_id", "dst_input_idx"), &AnimationTreePlayer::connect_nodes); - ClassDB::bind_method(D_METHOD("are_nodes_connected", "id", "dst_id", "dst_input_idx"), &AnimationTreePlayer::are_nodes_connected); - ClassDB::bind_method(D_METHOD("disconnect_nodes", "id", "dst_input_idx"), &AnimationTreePlayer::disconnect_nodes); - - ClassDB::bind_method(D_METHOD("set_active", "enabled"), &AnimationTreePlayer::set_active); - ClassDB::bind_method(D_METHOD("is_active"), &AnimationTreePlayer::is_active); - - ClassDB::bind_method(D_METHOD("set_base_path", "path"), &AnimationTreePlayer::set_base_path); - ClassDB::bind_method(D_METHOD("get_base_path"), &AnimationTreePlayer::get_base_path); - - ClassDB::bind_method(D_METHOD("set_master_player", "nodepath"), &AnimationTreePlayer::set_master_player); - ClassDB::bind_method(D_METHOD("get_master_player"), &AnimationTreePlayer::get_master_player); - - ClassDB::bind_method(D_METHOD("get_node_list"), &AnimationTreePlayer::_get_node_list); - - ClassDB::bind_method(D_METHOD("set_animation_process_mode", "mode"), &AnimationTreePlayer::set_animation_process_mode); - ClassDB::bind_method(D_METHOD("get_animation_process_mode"), &AnimationTreePlayer::get_animation_process_mode); - - ClassDB::bind_method(D_METHOD("advance", "delta"), &AnimationTreePlayer::advance); - - ClassDB::bind_method(D_METHOD("reset"), &AnimationTreePlayer::reset); - - ClassDB::bind_method(D_METHOD("recompute_caches"), &AnimationTreePlayer::recompute_caches); - - ADD_GROUP("Playback", "playback_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_animation_process_mode", "get_animation_process_mode"); - - ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "master_player", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "AnimationPlayer"), "set_master_player", "get_master_player"); - ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "base_path"), "set_base_path", "get_base_path"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "active"), "set_active", "is_active"); - - BIND_ENUM_CONSTANT(NODE_OUTPUT); - BIND_ENUM_CONSTANT(NODE_ANIMATION); - BIND_ENUM_CONSTANT(NODE_ONESHOT); - BIND_ENUM_CONSTANT(NODE_MIX); - BIND_ENUM_CONSTANT(NODE_BLEND2); - BIND_ENUM_CONSTANT(NODE_BLEND3); - BIND_ENUM_CONSTANT(NODE_BLEND4); - BIND_ENUM_CONSTANT(NODE_TIMESCALE); - BIND_ENUM_CONSTANT(NODE_TIMESEEK); - BIND_ENUM_CONSTANT(NODE_TRANSITION); - - BIND_ENUM_CONSTANT(ANIMATION_PROCESS_PHYSICS); - BIND_ENUM_CONSTANT(ANIMATION_PROCESS_IDLE); -} - -AnimationTreePlayer::AnimationTreePlayer() { - - active_list = NULL; - out = memnew(NodeOut); - out_name = "out"; - out->pos = Point2(40, 40); - node_map.insert(out_name, out); - animation_process_mode = ANIMATION_PROCESS_IDLE; - processing = false; - active = false; - dirty_caches = true; - reset_request = true; - last_error = CONNECT_INCOMPLETE; - base_path = String(".."); -} - -AnimationTreePlayer::~AnimationTreePlayer() { - - while (node_map.size()) { - memdelete(node_map.front()->get()); - node_map.erase(node_map.front()); - } -} diff --git a/scene/animation/animation_tree_player.h b/scene/animation/animation_tree_player.h deleted file mode 100644 index 9ec6325969..0000000000 --- a/scene/animation/animation_tree_player.h +++ /dev/null @@ -1,487 +0,0 @@ -/*************************************************************************/ -/* animation_tree_player.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef ANIMATION_TREE_PLAYER_H -#define ANIMATION_TREE_PLAYER_H - -#include "animation_player.h" -#include "scene/3d/skeleton.h" -#include "scene/3d/spatial.h" -#include "scene/resources/animation.h" - -class AnimationTreePlayer : public Node { - - GDCLASS(AnimationTreePlayer, Node); - OBJ_CATEGORY("Animation Nodes"); - -public: - enum AnimationProcessMode { - ANIMATION_PROCESS_PHYSICS, - ANIMATION_PROCESS_IDLE, - }; - - enum NodeType { - - NODE_OUTPUT, - NODE_ANIMATION, - NODE_ONESHOT, - NODE_MIX, - NODE_BLEND2, - NODE_BLEND3, - NODE_BLEND4, - NODE_TIMESCALE, - NODE_TIMESEEK, - NODE_TRANSITION, - - NODE_MAX, - }; - - enum ConnectError { - - CONNECT_OK, - CONNECT_INCOMPLETE, - CONNECT_CYCLE - }; - -private: - enum { - - DISCONNECTED = -1, - }; - - struct TrackKey { - - uint32_t id; - StringName subpath_concatenated; - int bone_idx; - - inline bool operator<(const TrackKey &p_right) const { - - if (id == p_right.id) { - if (bone_idx == p_right.bone_idx) { - return subpath_concatenated < p_right.subpath_concatenated; - } else - return bone_idx < p_right.bone_idx; - } else - return id < p_right.id; - } - }; - - struct Track { - uint32_t id; - Object *object; - Spatial *spatial; - Skeleton *skeleton; - int bone_idx; - Vector<StringName> subpath; - - Vector3 loc; - Quat rot; - Vector3 scale; - - Variant value; - - bool skip; - - Track() : - id(0), - object(NULL), - spatial(NULL), - skeleton(NULL), - bone_idx(-1), - skip(false) {} - }; - - typedef Map<TrackKey, Track> TrackMap; - - TrackMap track_map; - - struct Input { - - StringName node; - //Input() { node=-1; } - }; - - struct NodeBase { - - bool cycletest; - - NodeType type; - Point2 pos; - - Vector<Input> inputs; - - NodeBase() { cycletest = false; }; - virtual ~NodeBase() { cycletest = false; } - }; - - struct NodeOut : public NodeBase { - - NodeOut() { - type = NODE_OUTPUT; - inputs.resize(1); - } - }; - - struct AnimationNode : public NodeBase { - - Ref<Animation> animation; - - struct TrackRef { - int local_track; - Track *track; - float weight; - }; - - uint64_t last_version; - List<TrackRef> tref; - AnimationNode *next; - float time; - float step; - String from; - bool skip; - - HashMap<NodePath, bool> filter; - - AnimationNode() { - type = NODE_ANIMATION; - next = NULL; - last_version = 0; - skip = false; - } - }; - - struct OneShotNode : public NodeBase { - - bool active; - bool start; - float fade_in; - float fade_out; - - bool autorestart; - float autorestart_delay; - float autorestart_random_delay; - bool mix; - - float time; - float remaining; - float autorestart_remaining; - - HashMap<NodePath, bool> filter; - - OneShotNode() { - type = NODE_ONESHOT; - fade_in = 0; - fade_out = 0; - inputs.resize(2); - autorestart = false; - autorestart_delay = 1; - autorestart_remaining = 0; - mix = false; - active = false; - start = false; - } - }; - - struct MixNode : public NodeBase { - - float amount; - MixNode() { - type = NODE_MIX; - inputs.resize(2); - } - }; - - struct Blend2Node : public NodeBase { - - float value; - HashMap<NodePath, bool> filter; - Blend2Node() { - type = NODE_BLEND2; - value = 0; - inputs.resize(2); - } - }; - - struct Blend3Node : public NodeBase { - - float value; - Blend3Node() { - type = NODE_BLEND3; - value = 0; - inputs.resize(3); - } - }; - - struct Blend4Node : public NodeBase { - - Point2 value; - Blend4Node() { - type = NODE_BLEND4; - inputs.resize(4); - } - }; - - struct TimeScaleNode : public NodeBase { - - float scale; - TimeScaleNode() { - type = NODE_TIMESCALE; - scale = 1; - inputs.resize(1); - } - }; - - struct TimeSeekNode : public NodeBase { - - float seek_pos; - - TimeSeekNode() { - type = NODE_TIMESEEK; - inputs.resize(1); - seek_pos = -1; - } - }; - - struct TransitionNode : public NodeBase { - - struct InputData { - - bool auto_advance; - InputData() { auto_advance = false; } - }; - - Vector<InputData> input_data; - - float prev_time; - float prev_xfading; - int prev; - bool switched; - - float time; - int current; - - float xfade; - - TransitionNode() { - type = NODE_TRANSITION; - xfade = 0; - inputs.resize(1); - input_data.resize(1); - current = 0; - prev = -1; - prev_time = 0; - prev_xfading = 0; - switched = false; - } - void set_current(int p_current); - }; - - void _update_sources(); - - StringName out_name; - NodeOut *out; - - NodePath base_path; - NodePath master; - - ConnectError last_error; - AnimationNode *active_list; - AnimationProcessMode animation_process_mode; - bool processing; - bool active; - bool dirty_caches; - Map<StringName, NodeBase *> node_map; - - // return time left to finish animation - float _process_node(const StringName &p_node, AnimationNode **r_prev_anim, float p_time, bool p_seek = false, float p_fallback_weight = 1.0, HashMap<NodePath, float> *p_weights = NULL); - void _process_animation(float p_delta); - bool reset_request; - - ConnectError _cycle_test(const StringName &p_at_node); - void _clear_cycle_test(); - - Track *_find_track(const NodePath &p_path); - void _recompute_caches(); - void _recompute_caches(const StringName &p_node); - PoolVector<String> _get_node_list(); - - void _compute_weights(float *p_fallback_weight, HashMap<NodePath, float> *p_weights, float p_coeff, const HashMap<NodePath, bool> *p_filter = NULL, float p_filtered_coeff = 0); - -protected: - bool _set(const StringName &p_name, const Variant &p_value); - bool _get(const StringName &p_name, Variant &r_ret) const; - void _get_property_list(List<PropertyInfo> *p_list) const; - void _notification(int p_what); - - static void _bind_methods(); - -public: - void add_node(NodeType p_type, const StringName &p_node); // nodes must be >0 node 0 is built-in (exit) - bool node_exists(const StringName &p_name) const; - - Error node_rename(const StringName &p_node, const StringName &p_new_name); - int node_get_input_count(const StringName &p_node) const; - StringName node_get_input_source(const StringName &p_node, int p_input) const; - - String get_configuration_warning() const; - - /* ANIMATION NODE */ - void animation_node_set_animation(const StringName &p_node, const Ref<Animation> &p_animation); - Ref<Animation> animation_node_get_animation(const StringName &p_node) const; - void animation_node_set_master_animation(const StringName &p_node, const String &p_master_animation); - String animation_node_get_master_animation(const StringName &p_node) const; - float animation_node_get_position(const StringName &p_node) const; - - void animation_node_set_filter_path(const StringName &p_node, const NodePath &p_track_path, bool p_filter); - void animation_node_set_get_filtered_paths(const StringName &p_node, List<NodePath> *r_paths) const; - bool animation_node_is_path_filtered(const StringName &p_node, const NodePath &p_path) const; - - /* ONE SHOT NODE */ - - void oneshot_node_set_fadein_time(const StringName &p_node, float p_time); - void oneshot_node_set_fadeout_time(const StringName &p_node, float p_time); - - float oneshot_node_get_fadein_time(const StringName &p_node) const; - float oneshot_node_get_fadeout_time(const StringName &p_node) const; - - void oneshot_node_set_autorestart(const StringName &p_node, bool p_active); - void oneshot_node_set_autorestart_delay(const StringName &p_node, float p_time); - void oneshot_node_set_autorestart_random_delay(const StringName &p_node, float p_time); - - bool oneshot_node_has_autorestart(const StringName &p_node) const; - float oneshot_node_get_autorestart_delay(const StringName &p_node) const; - float oneshot_node_get_autorestart_random_delay(const StringName &p_node) const; - - void oneshot_node_set_mix_mode(const StringName &p_node, bool p_mix); - bool oneshot_node_get_mix_mode(const StringName &p_node) const; - - void oneshot_node_start(const StringName &p_node); - void oneshot_node_stop(const StringName &p_node); - bool oneshot_node_is_active(const StringName &p_node) const; - - void oneshot_node_set_filter_path(const StringName &p_node, const NodePath &p_filter, bool p_enable); - void oneshot_node_set_get_filtered_paths(const StringName &p_node, List<NodePath> *r_paths) const; - bool oneshot_node_is_path_filtered(const StringName &p_node, const NodePath &p_path) const; - - /* MIX/BLEND NODES */ - - void mix_node_set_amount(const StringName &p_node, float p_amount); - float mix_node_get_amount(const StringName &p_node) const; - - void blend2_node_set_amount(const StringName &p_node, float p_amount); - float blend2_node_get_amount(const StringName &p_node) const; - void blend2_node_set_filter_path(const StringName &p_node, const NodePath &p_filter, bool p_enable); - void blend2_node_set_get_filtered_paths(const StringName &p_node, List<NodePath> *r_paths) const; - bool blend2_node_is_path_filtered(const StringName &p_node, const NodePath &p_path) const; - - void blend3_node_set_amount(const StringName &p_node, float p_amount); - float blend3_node_get_amount(const StringName &p_node) const; - - void blend4_node_set_amount(const StringName &p_node, const Point2 &p_amount); - Point2 blend4_node_get_amount(const StringName &p_node) const; - - /* TIMESCALE/TIMESEEK NODES */ - - void timescale_node_set_scale(const StringName &p_node, float p_scale); - float timescale_node_get_scale(const StringName &p_node) const; - - void timeseek_node_seek(const StringName &p_node, float p_pos); - - /* TRANSITION NODE */ - - void transition_node_set_input_count(const StringName &p_node, int p_inputs); // used for transition node - int transition_node_get_input_count(const StringName &p_node) const; - void transition_node_delete_input(const StringName &p_node, int p_input); // used for transition node - - void transition_node_set_input_auto_advance(const StringName &p_node, int p_input, bool p_auto_advance); // used for transition node - bool transition_node_has_input_auto_advance(const StringName &p_node, int p_input) const; - - void transition_node_set_xfade_time(const StringName &p_node, float p_time); // used for transition node - float transition_node_get_xfade_time(const StringName &p_node) const; - - void transition_node_set_current(const StringName &p_node, int p_current); - int transition_node_get_current(const StringName &p_node) const; - - void node_set_position(const StringName &p_node, const Vector2 &p_pos); //for display - - /* GETS */ - Point2 node_get_position(const StringName &p_node) const; //for display - - NodeType node_get_type(const StringName &p_node) const; - - void get_node_list(List<StringName> *p_node_list) const; - void remove_node(const StringName &p_node); - - Error connect_nodes(const StringName &p_src_node, const StringName &p_dst_node, int p_dst_input); - bool are_nodes_connected(const StringName &p_src_node, const StringName &p_dst_node, int p_dst_input) const; - void disconnect_nodes(const StringName &p_node, int p_input); - - void set_base_path(const NodePath &p_path); - NodePath get_base_path() const; - - void set_master_player(const NodePath &p_path); - NodePath get_master_player() const; - - struct Connection { - - StringName src_node; - StringName dst_node; - int dst_input; - }; - - void get_connection_list(List<Connection> *p_connections) const; - - /* playback */ - - void set_active(bool p_active); - bool is_active() const; - - void reset(); - - void recompute_caches(); - - ConnectError get_last_error() const; - - void set_animation_process_mode(AnimationProcessMode p_mode); - AnimationProcessMode get_animation_process_mode() const; - - void _set_process(bool p_process, bool p_force = false); - - void advance(float p_time); - - AnimationTreePlayer(); - ~AnimationTreePlayer(); -}; - -VARIANT_ENUM_CAST(AnimationTreePlayer::NodeType); -VARIANT_ENUM_CAST(AnimationTreePlayer::AnimationProcessMode); - -#endif // ANIMATION_TREE_PLAYER_H diff --git a/scene/animation/root_motion_view.cpp b/scene/animation/root_motion_view.cpp index 646a39d063..32ceeb4dbf 100644 --- a/scene/animation/root_motion_view.cpp +++ b/scene/animation/root_motion_view.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/animation/root_motion_view.h b/scene/animation/root_motion_view.h index b30b06229e..0a255cb5d2 100644 --- a/scene/animation/root_motion_view.h +++ b/scene/animation/root_motion_view.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/animation/skeleton_ik.cpp b/scene/animation/skeleton_ik.cpp index 4ec22cf3df..518c243dd0 100644 --- a/scene/animation/skeleton_ik.cpp +++ b/scene/animation/skeleton_ik.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -320,7 +320,7 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove new_bone_pose.basis = new_bone_pose.basis * p_task->chain.tips[0].end_effector->goal_transform.basis; } - p_task->skeleton->set_bone_global_pose_override(ci->bone, new_bone_pose, 1.0); + p_task->skeleton->set_bone_global_pose_override(ci->bone, new_bone_pose, 1.0, true); if (!ci->children.empty()) ci = &ci->children.write[0]; diff --git a/scene/animation/skeleton_ik.h b/scene/animation/skeleton_ik.h index d2c5f56ace..9ae010dc4e 100644 --- a/scene/animation/skeleton_ik.h +++ b/scene/animation/skeleton_ik.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index a7d936fcd3..331a6c769c 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -63,6 +63,8 @@ void Tween::_add_pending_command(StringName p_key, const Variant &p_arg1, const count = 2; else if (p_arg1.get_type() != Variant::NIL) count = 1; + else + count = 0; // Add the specified arguments to the command // TODO: Make this a switch statement? @@ -237,14 +239,14 @@ void Tween::_bind_methods() { ClassDB::bind_method(D_METHOD("get_runtime"), &Tween::get_runtime); // Bind interpolation and follow methods - ClassDB::bind_method(D_METHOD("interpolate_property", "object", "property", "initial_val", "final_val", "duration", "trans_type", "ease_type", "delay"), &Tween::interpolate_property, DEFVAL(0)); - ClassDB::bind_method(D_METHOD("interpolate_method", "object", "method", "initial_val", "final_val", "duration", "trans_type", "ease_type", "delay"), &Tween::interpolate_method, DEFVAL(0)); + ClassDB::bind_method(D_METHOD("interpolate_property", "object", "property", "initial_val", "final_val", "duration", "trans_type", "ease_type", "delay"), &Tween::interpolate_property, DEFVAL(TRANS_LINEAR), DEFVAL(EASE_IN_OUT), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("interpolate_method", "object", "method", "initial_val", "final_val", "duration", "trans_type", "ease_type", "delay"), &Tween::interpolate_method, DEFVAL(TRANS_LINEAR), DEFVAL(EASE_IN_OUT), DEFVAL(0)); ClassDB::bind_method(D_METHOD("interpolate_callback", "object", "duration", "callback", "arg1", "arg2", "arg3", "arg4", "arg5"), &Tween::interpolate_callback, DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("interpolate_deferred_callback", "object", "duration", "callback", "arg1", "arg2", "arg3", "arg4", "arg5"), &Tween::interpolate_deferred_callback, DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant())); - ClassDB::bind_method(D_METHOD("follow_property", "object", "property", "initial_val", "target", "target_property", "duration", "trans_type", "ease_type", "delay"), &Tween::follow_property, DEFVAL(0)); - ClassDB::bind_method(D_METHOD("follow_method", "object", "method", "initial_val", "target", "target_method", "duration", "trans_type", "ease_type", "delay"), &Tween::follow_method, DEFVAL(0)); - ClassDB::bind_method(D_METHOD("targeting_property", "object", "property", "initial", "initial_val", "final_val", "duration", "trans_type", "ease_type", "delay"), &Tween::targeting_property, DEFVAL(0)); - ClassDB::bind_method(D_METHOD("targeting_method", "object", "method", "initial", "initial_method", "final_val", "duration", "trans_type", "ease_type", "delay"), &Tween::targeting_method, DEFVAL(0)); + ClassDB::bind_method(D_METHOD("follow_property", "object", "property", "initial_val", "target", "target_property", "duration", "trans_type", "ease_type", "delay"), &Tween::follow_property, DEFVAL(TRANS_LINEAR), DEFVAL(EASE_IN_OUT), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("follow_method", "object", "method", "initial_val", "target", "target_method", "duration", "trans_type", "ease_type", "delay"), &Tween::follow_method, DEFVAL(TRANS_LINEAR), DEFVAL(EASE_IN_OUT), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("targeting_property", "object", "property", "initial", "initial_val", "final_val", "duration", "trans_type", "ease_type", "delay"), &Tween::targeting_property, DEFVAL(TRANS_LINEAR), DEFVAL(EASE_IN_OUT), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("targeting_method", "object", "method", "initial", "initial_method", "final_val", "duration", "trans_type", "ease_type", "delay"), &Tween::targeting_method, DEFVAL(TRANS_LINEAR), DEFVAL(EASE_IN_OUT), DEFVAL(0)); // Add the Tween signals ADD_SIGNAL(MethodInfo("tween_started", PropertyInfo(Variant::OBJECT, "object"), PropertyInfo(Variant::NODE_PATH, "key"))); @@ -825,6 +827,7 @@ bool Tween::start() { // Are there any pending updates? if (pending_update != 0) { // Start the tweens after deferring + call_deferred("start"); return true; } diff --git a/scene/animation/tween.h b/scene/animation/tween.h index 574238f5c9..f1218cd698 100644 --- a/scene/animation/tween.h +++ b/scene/animation/tween.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -101,6 +101,12 @@ private: int args; Variant arg[5]; int uid; + InterpolateData() { + active = false; + finish = false; + call_deferred = false; + uid = 0; + } }; String autoplay; @@ -173,21 +179,14 @@ public: real_t tell() const; real_t get_runtime() const; - bool interpolate_property(Object *p_object, NodePath p_property, Variant p_initial_val, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0); - - bool interpolate_method(Object *p_object, StringName p_method, Variant p_initial_val, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0); - + bool interpolate_property(Object *p_object, NodePath p_property, Variant p_initial_val, Variant p_final_val, real_t p_duration, TransitionType p_trans_type = TRANS_LINEAR, EaseType p_ease_type = EASE_IN_OUT, real_t p_delay = 0); + bool interpolate_method(Object *p_object, StringName p_method, Variant p_initial_val, Variant p_final_val, real_t p_duration, TransitionType p_trans_type = TRANS_LINEAR, EaseType p_ease_type = EASE_IN_OUT, real_t p_delay = 0); bool interpolate_callback(Object *p_object, real_t p_duration, String p_callback, VARIANT_ARG_DECLARE); - bool interpolate_deferred_callback(Object *p_object, real_t p_duration, String p_callback, VARIANT_ARG_DECLARE); - - bool follow_property(Object *p_object, NodePath p_property, Variant p_initial_val, Object *p_target, NodePath p_target_property, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0); - - bool follow_method(Object *p_object, StringName p_method, Variant p_initial_val, Object *p_target, StringName p_target_method, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0); - - bool targeting_property(Object *p_object, NodePath p_property, Object *p_initial, NodePath p_initial_property, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0); - - bool targeting_method(Object *p_object, StringName p_method, Object *p_initial, StringName p_initial_method, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0); + bool follow_property(Object *p_object, NodePath p_property, Variant p_initial_val, Object *p_target, NodePath p_target_property, real_t p_duration, TransitionType p_trans_type = TRANS_LINEAR, EaseType p_ease_type = EASE_IN_OUT, real_t p_delay = 0); + bool follow_method(Object *p_object, StringName p_method, Variant p_initial_val, Object *p_target, StringName p_target_method, real_t p_duration, TransitionType p_trans_type = TRANS_LINEAR, EaseType p_ease_type = EASE_IN_OUT, real_t p_delay = 0); + bool targeting_property(Object *p_object, NodePath p_property, Object *p_initial, NodePath p_initial_property, Variant p_final_val, real_t p_duration, TransitionType p_trans_type = TRANS_LINEAR, EaseType p_ease_type = EASE_IN_OUT, real_t p_delay = 0); + bool targeting_method(Object *p_object, StringName p_method, Object *p_initial, StringName p_initial_method, Variant p_final_val, real_t p_duration, TransitionType p_trans_type = TRANS_LINEAR, EaseType p_ease_type = EASE_IN_OUT, real_t p_delay = 0); Tween(); ~Tween(); diff --git a/scene/audio/audio_stream_player.cpp b/scene/audio/audio_stream_player.cpp index c053fceb74..3a0169f065 100644 --- a/scene/audio/audio_stream_player.cpp +++ b/scene/audio/audio_stream_player.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/audio/audio_stream_player.h b/scene/audio/audio_stream_player.h index ab9161c798..0f6d855d0e 100644 --- a/scene/audio/audio_stream_player.h +++ b/scene/audio/audio_stream_player.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/debugger/script_debugger_remote.cpp b/scene/debugger/script_debugger_remote.cpp index c3c6a088cb..0a075df060 100644 --- a/scene/debugger/script_debugger_remote.cpp +++ b/scene/debugger/script_debugger_remote.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -92,7 +92,7 @@ Error ScriptDebuggerRemote::connect_to_host(const String &p_host, uint16_t p_por if (tcp_client->get_status() != StreamPeerTCP::STATUS_CONNECTED) { - ERR_PRINTS("Remote Debugger: Unable to connect. Status: " + String::num(tcp_client->get_status()) + "."); + ERR_PRINT("Remote Debugger: Unable to connect. Status: " + String::num(tcp_client->get_status()) + "."); return FAILED; }; @@ -1257,7 +1257,7 @@ ScriptDebuggerRemote::ScriptDebuggerRemote() : scene_tree(NULL) { packet_peer_stream->set_stream_peer(tcp_client); - packet_peer_stream->set_output_buffer_max_size(1024 * 1024 * 8); //8mb should be way more than enough + packet_peer_stream->set_output_buffer_max_size((1024 * 1024 * 8) - 4); // 8 MiB should be way more than enough, minus 4 bytes for separator. phl.printfunc = _print_handler; phl.userdata = this; diff --git a/scene/debugger/script_debugger_remote.h b/scene/debugger/script_debugger_remote.h index 13ad7ddbe3..2c0dccdaf7 100644 --- a/scene/debugger/script_debugger_remote.h +++ b/scene/debugger/script_debugger_remote.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index 4f71481280..b2020d44e8 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -165,15 +165,23 @@ void BaseButton::on_action_event(Ref<InputEvent> p_event) { _pressed(); } } else { - if (!p_event->is_pressed()) { + if ((p_event->is_pressed() && action_mode == ACTION_MODE_BUTTON_PRESS) || (!p_event->is_pressed() && action_mode == ACTION_MODE_BUTTON_RELEASE)) { _pressed(); } } } - if (!p_event->is_pressed()) { // pressed state should be correct with button_up signal + if (!p_event->is_pressed()) { + Ref<InputEventMouseButton> mouse_button = p_event; + if (mouse_button.is_valid()) { + if (!has_point(mouse_button->get_position())) { + status.hovering = false; + } + } + // pressed state should be correct with button_up signal emit_signal("button_up"); status.press_attempt = false; + status.pressing_inside = false; } update(); diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h index 2773f024df..21757488a6 100644 --- a/scene/gui/base_button.h +++ b/scene/gui/base_button.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp index b7d2131ee9..e0bfeac9f7 100644 --- a/scene/gui/box_container.cpp +++ b/scene/gui/box_container.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -289,8 +289,6 @@ BoxContainer::BoxContainer(bool p_vertical) { vertical = p_vertical; align = ALIGN_BEGIN; - //set_ignore_mouse(true); - set_mouse_filter(MOUSE_FILTER_PASS); } void BoxContainer::_bind_methods() { diff --git a/scene/gui/box_container.h b/scene/gui/box_container.h index 89924f7fcb..0d7deda364 100644 --- a/scene/gui/box_container.h +++ b/scene/gui/box_container.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp index ca4c255855..6f3d8c61cf 100644 --- a/scene/gui/button.cpp +++ b/scene/gui/button.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -190,6 +190,13 @@ void Button::_notification(int p_what) { Point2 icon_ofs = !_icon.is_null() ? Point2(icon_region.size.width + get_constant("hseparation"), 0) : Point2(); int text_clip = size.width - style->get_minimum_size().width - icon_ofs.width; + if (_internal_margin[MARGIN_LEFT] > 0) { + text_clip -= _internal_margin[MARGIN_LEFT] + get_constant("hseparation"); + } + if (_internal_margin[MARGIN_RIGHT] > 0) { + text_clip -= _internal_margin[MARGIN_RIGHT] + get_constant("hseparation"); + } + Point2 text_ofs = (size - style->get_minimum_size() - icon_ofs - font->get_string_size(xl_text) - Point2(_internal_margin[MARGIN_RIGHT] - _internal_margin[MARGIN_LEFT], 0)) / 2.0; switch (align) { diff --git a/scene/gui/button.h b/scene/gui/button.h index 1fff2cfda7..e975dc52a5 100644 --- a/scene/gui/button.h +++ b/scene/gui/button.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/center_container.cpp b/scene/gui/center_container.cpp index 7c842999d1..64d6885bc8 100644 --- a/scene/gui/center_container.cpp +++ b/scene/gui/center_container.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -54,7 +54,13 @@ Size2 CenterContainer::get_minimum_size() const { void CenterContainer::set_use_top_left(bool p_enable) { + if (use_top_left == p_enable) { + return; + } + use_top_left = p_enable; + + minimum_size_changed(); queue_sort(); } diff --git a/scene/gui/center_container.h b/scene/gui/center_container.h index 9c9f61388c..98733f384d 100644 --- a/scene/gui/center_container.h +++ b/scene/gui/center_container.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp index 8744407763..443121db32 100644 --- a/scene/gui/check_box.cpp +++ b/scene/gui/check_box.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/check_box.h b/scene/gui/check_box.h index adfb12e7a1..7c8f8c11d6 100644 --- a/scene/gui/check_box.h +++ b/scene/gui/check_box.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/check_button.cpp b/scene/gui/check_button.cpp index f47547f2cc..9d6df94cce 100644 --- a/scene/gui/check_button.cpp +++ b/scene/gui/check_button.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/check_button.h b/scene/gui/check_button.h index 13b0dbc194..3599c26a4c 100644 --- a/scene/gui/check_button.h +++ b/scene/gui/check_button.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 96b62b97f9..01f4070883 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -573,9 +573,7 @@ void ColorPicker::_preset_input(const Ref<InputEvent> &p_event) { } if (index < 0 || index >= presets.size()) return; - preset->set_tooltip("Color: #" + presets[index].to_html(presets[index].a < 1) + "\n" - "LMB: Set color\n" - "RMB: Remove preset"); + preset->set_tooltip(vformat(RTR("Color: #%s\nLMB: Set color\nRMB: Remove preset"), presets[index].to_html(presets[index].a < 1))); } } @@ -737,20 +735,6 @@ ColorPicker::ColorPicker() : presets_visible = true; screen = NULL; - HBoxContainer *hb_smpl = memnew(HBoxContainer); - add_child(hb_smpl); - - sample = memnew(TextureRect); - hb_smpl->add_child(sample); - sample->set_h_size_flags(SIZE_EXPAND_FILL); - sample->connect("draw", this, "_sample_draw"); - - btn_pick = memnew(ToolButton); - hb_smpl->add_child(btn_pick); - btn_pick->set_toggle_mode(true); - btn_pick->set_tooltip(TTR("Pick a color from the screen.")); - btn_pick->connect("pressed", this, "_screen_pick_pressed"); - HBoxContainer *hb_edit = memnew(HBoxContainer); add_child(hb_edit); hb_edit->set_v_size_flags(SIZE_EXPAND_FILL); @@ -772,6 +756,20 @@ ColorPicker::ColorPicker() : w_edit->connect("gui_input", this, "_w_input"); w_edit->connect("draw", this, "_hsv_draw", make_binds(1, w_edit)); + HBoxContainer *hb_smpl = memnew(HBoxContainer); + add_child(hb_smpl); + + sample = memnew(TextureRect); + hb_smpl->add_child(sample); + sample->set_h_size_flags(SIZE_EXPAND_FILL); + sample->connect("draw", this, "_sample_draw"); + + btn_pick = memnew(ToolButton); + hb_smpl->add_child(btn_pick); + btn_pick->set_toggle_mode(true); + btn_pick->set_tooltip(TTR("Pick a color from the editor window.")); + btn_pick->connect("pressed", this, "_screen_pick_pressed"); + VBoxContainer *vbl = memnew(VBoxContainer); add_child(vbl); diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index 167f7b33b3..49d36dfb3a 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/color_rect.cpp b/scene/gui/color_rect.cpp index df9b4e8498..61260e153c 100644 --- a/scene/gui/color_rect.cpp +++ b/scene/gui/color_rect.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/color_rect.h b/scene/gui/color_rect.h index 7a7bbe1029..3df44b9334 100644 --- a/scene/gui/color_rect.h +++ b/scene/gui/color_rect.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp index 449076f863..b411f563b8 100644 --- a/scene/gui/container.cpp +++ b/scene/gui/container.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -197,4 +197,6 @@ void Container::_bind_methods() { Container::Container() { pending_sort = false; + // All containers should let mouse events pass by default. + set_mouse_filter(MOUSE_FILTER_PASS); } diff --git a/scene/gui/container.h b/scene/gui/container.h index 80d3f6ee5d..0b736d9790 100644 --- a/scene/gui/container.h +++ b/scene/gui/container.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 8b4d5d4980..4c70bd1d39 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -47,6 +47,7 @@ #include "editor/plugins/canvas_item_editor_plugin.h" #endif +#ifdef TOOLS_ENABLED Dictionary Control::_edit_get_state() const { Dictionary s; @@ -155,6 +156,11 @@ bool Control::_edit_use_pivot() const { return true; } +Size2 Control::_edit_get_minimum_size() const { + return get_combined_minimum_size(); +} +#endif + void Control::set_custom_minimum_size(const Size2 &p_custom) { if (p_custom == data.custom_minimum_size) @@ -193,11 +199,6 @@ Size2 Control::get_combined_minimum_size() const { return data.minimum_size_cache; } -Size2 Control::_edit_get_minimum_size() const { - - return get_combined_minimum_size(); -} - Transform2D Control::_get_internal_transform() const { Transform2D rot_scale; @@ -461,11 +462,6 @@ void Control::_update_canvas_item_transform() { Transform2D xform = _get_internal_transform(); xform[2] += get_position(); - // We use a little workaround to avoid flickering when moving the pivot with _edit_set_pivot() - if (is_inside_tree() && Math::abs(Math::sin(data.rotation * 4.0f)) < 0.00001f && get_viewport()->is_snap_controls_to_pixels_enabled()) { - xform[2] = xform[2].round(); - } - VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), xform); } @@ -2012,14 +2008,15 @@ Control *Control::find_next_valid_focus() const { if (!data.focus_next.is_empty()) { Node *n = get_node(data.focus_next); + Control *c; if (n) { - from = Object::cast_to<Control>(n); - ERR_FAIL_COND_V_MSG(!from, NULL, "Next focus node is not a control: " + n->get_name() + "."); + c = Object::cast_to<Control>(n); + ERR_FAIL_COND_V_MSG(!c, NULL, "Next focus node is not a control: " + n->get_name() + "."); } else { return NULL; } - if (from->is_visible() && from->get_focus_mode() != FOCUS_NONE) - return from; + if (c->is_visible() && c->get_focus_mode() != FOCUS_NONE) + return c; } // find next child @@ -2102,14 +2099,15 @@ Control *Control::find_prev_valid_focus() const { if (!data.focus_prev.is_empty()) { Node *n = get_node(data.focus_prev); + Control *c; if (n) { - from = Object::cast_to<Control>(n); - ERR_FAIL_COND_V_MSG(!from, NULL, "Previous focus node is not a control: " + n->get_name() + "."); + c = Object::cast_to<Control>(n); + ERR_FAIL_COND_V_MSG(!c, NULL, "Previous focus node is not a control: " + n->get_name() + "."); } else { return NULL; } - if (from->is_visible() && from->get_focus_mode() != FOCUS_NONE) - return from; + if (c->is_visible() && c->get_focus_mode() != FOCUS_NONE) + return c; } // find prev child @@ -2284,7 +2282,7 @@ void Control::set_theme(const Ref<Theme> &p_theme) { } if (data.theme.is_valid()) { - data.theme->connect("changed", this, "_theme_changed"); + data.theme->connect("changed", this, "_theme_changed", varray(), CONNECT_DEFERRED); } } @@ -2472,9 +2470,9 @@ void Control::_window_find_focus_neighbour(const Vector2 &p_dir, Node *p_at, con Transform2D xform = c->get_global_transform(); 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)); + points[1] = xform.xform(Point2(c->get_size().x, 0)); + points[2] = xform.xform(c->get_size()); + points[3] = xform.xform(Point2(0, c->get_size().y)); float min = 1e7; @@ -2679,6 +2677,11 @@ Vector2 Control::get_pivot_offset() const { void Control::set_scale(const Vector2 &p_scale) { data.scale = p_scale; + // Avoid having 0 scale values, can lead to errors in physics and rendering. + if (data.scale.x == 0) + data.scale.x = CMP_EPSILON; + if (data.scale.y == 0) + data.scale.y = CMP_EPSILON; update(); _notify_transform(); } diff --git a/scene/gui/control.h b/scene/gui/control.h index 7305b3ce93..357858beb6 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -279,6 +279,7 @@ public: }; /* EDITOR */ +#ifdef TOOLS_ENABLED virtual Dictionary _edit_get_state() const; virtual void _edit_set_state(const Dictionary &p_state); @@ -301,6 +302,7 @@ public: virtual bool _edit_use_pivot() const; virtual Size2 _edit_get_minimum_size() const; +#endif void accept_event(); diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index a1b584bad6..e0e88e1577 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -35,6 +35,7 @@ #ifdef TOOLS_ENABLED #include "editor/editor_node.h" +#include "editor/editor_scale.h" #include "scene/main/viewport.h" // Only used to check for more modals when dimming the editor. #endif @@ -161,7 +162,7 @@ void WindowDialog::_gui_input(const Ref<InputEvent> &p_event) { global_pos.y = MAX(global_pos.y, 0); // Ensure title bar stays visible. Rect2 rect = get_rect(); - Size2 min_size = get_minimum_size(); + Size2 min_size = get_combined_minimum_size(); if (drag_type == DRAG_MOVE) { rect.position = global_pos - drag_offset; @@ -443,7 +444,9 @@ bool AcceptDialog::has_autowrap() { void AcceptDialog::register_text_enter(Node *p_line_edit) { ERR_FAIL_NULL(p_line_edit); - p_line_edit->connect("text_entered", this, "_builtin_text_entered"); + LineEdit *line_edit = Object::cast_to<LineEdit>(p_line_edit); + if (line_edit) + line_edit->connect("text_entered", this, "_builtin_text_entered"); } void AcceptDialog::_update_child_rects() { diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h index 2eb0978e9b..b6381e98b4 100644 --- a/scene/gui/dialogs.h +++ b/scene/gui/dialogs.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 6400061309..2cc9c1a53a 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -558,25 +558,25 @@ void FileDialog::update_filters() { const int max_filters = 5; for (int i = 0; i < MIN(max_filters, filters.size()); i++) { - String flt = filters[i].get_slice(";", 0); + String flt = filters[i].get_slice(";", 0).strip_edges(); if (i > 0) - all_filters += ","; + all_filters += ", "; all_filters += flt; } if (max_filters < filters.size()) all_filters += ", ..."; - filter->add_item(RTR("All Recognized") + " ( " + all_filters + " )"); + filter->add_item(RTR("All Recognized") + " (" + all_filters + ")"); } for (int i = 0; i < filters.size(); i++) { String flt = filters[i].get_slice(";", 0).strip_edges(); String desc = filters[i].get_slice(";", 1).strip_edges(); if (desc.length()) - filter->add_item(String(tr(desc)) + " ( " + flt + " )"); + filter->add_item(String(tr(desc)) + " (" + flt + ")"); else - filter->add_item("( " + flt + " )"); + filter->add_item("(" + flt + ")"); } filter->add_item(RTR("All Files (*)")); diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h index 687ebc8036..d9ab00e0f2 100644 --- a/scene/gui/file_dialog.h +++ b/scene/gui/file_dialog.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp index 09ef6f26bf..46c59f42fc 100644 --- a/scene/gui/gradient_edit.cpp +++ b/scene/gui/gradient_edit.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -277,12 +277,13 @@ void GradientEdit::_gui_input(const Ref<InputEvent> &p_event) { if (points[i].offset == newofs && i != grabbed) { valid = false; + break; } } - if (!valid) + if (!valid || grabbed == -1) { return; - + } points.write[grabbed].offset = newofs; points.sort(); diff --git a/scene/gui/gradient_edit.h b/scene/gui/gradient_edit.h index 6f31107729..a38a3dde47 100644 --- a/scene/gui/gradient_edit.h +++ b/scene/gui/gradient_edit.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index ed9fc0ce51..c09b2414b2 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -200,6 +200,13 @@ void GraphEdit::_update_scroll() { else v_scroll->show(); + Size2 hmin = h_scroll->get_combined_minimum_size(); + Size2 vmin = v_scroll->get_combined_minimum_size(); + + // Avoid scrollbar overlapping. + h_scroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, v_scroll->is_visible() ? -vmin.width : 0); + v_scroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, h_scroll->is_visible() ? -hmin.height : 0); + set_block_minimum_size_adjust(false); if (!awaiting_scroll_offset_update) { @@ -286,15 +293,15 @@ void GraphEdit::_notification(int p_what) { Size2 hmin = h_scroll->get_combined_minimum_size(); Size2 vmin = v_scroll->get_combined_minimum_size(); - v_scroll->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -vmin.width); - v_scroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0); - v_scroll->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 0); - v_scroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0); - h_scroll->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 0); h_scroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0); h_scroll->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, -hmin.height); h_scroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0); + + v_scroll->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -vmin.width); + v_scroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0); + v_scroll->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 0); + v_scroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0); } if (p_what == NOTIFICATION_DRAW) { @@ -777,14 +784,8 @@ void GraphEdit::_top_layer_draw() { } if (box_selecting) { - top_layer->draw_rect( - box_selecting_rect, - get_color("box_selection_fill_color", "Editor")); - - top_layer->draw_rect( - box_selecting_rect, - get_color("box_selection_stroke_color", "Editor"), - false); + top_layer->draw_rect(box_selecting_rect, get_color("selection_fill")); + top_layer->draw_rect(box_selecting_rect, get_color("selection_stroke"), false); } } @@ -1341,7 +1342,6 @@ GraphEdit::GraphEdit() { top_layer->set_mouse_filter(MOUSE_FILTER_PASS); top_layer->set_anchors_and_margins_preset(Control::PRESET_WIDE); top_layer->connect("draw", this, "_top_layer_draw"); - top_layer->set_mouse_filter(MOUSE_FILTER_PASS); top_layer->connect("gui_input", this, "_top_layer_input"); connections_layer = memnew(Control); @@ -1358,6 +1358,7 @@ GraphEdit::GraphEdit() { v_scroll = memnew(VScrollBar); v_scroll->set_name("_v_scroll"); top_layer->add_child(v_scroll); + updating = false; connecting = false; right_disconnects = false; diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index de826bf505..7f1d2699ba 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index 5b2f8812d5..7b1bfdfdb5 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h index 2179904cc4..e1a81b5f3d 100644 --- a/scene/gui/graph_node.h +++ b/scene/gui/graph_node.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp index 154e67b6f3..0028093a95 100644 --- a/scene/gui/grid_container.cpp +++ b/scene/gui/grid_container.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -247,7 +247,5 @@ Size2 GridContainer::get_minimum_size() const { } GridContainer::GridContainer() { - - set_mouse_filter(MOUSE_FILTER_PASS); columns = 1; } diff --git a/scene/gui/grid_container.h b/scene/gui/grid_container.h index 3196046378..0ed8863196 100644 --- a/scene/gui/grid_container.h +++ b/scene/gui/grid_container.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 1406586361..526950dbb3 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -969,7 +969,7 @@ void ItemList::_notification(int p_what) { } if (all_fit) { - float page = size.height - bg->get_minimum_size().height; + float page = MAX(0, size.height - bg->get_minimum_size().height); float max = MAX(page, ofs.y + max_h); if (auto_height) auto_height_value = ofs.y + max_h + bg->get_minimum_size().height; @@ -993,7 +993,7 @@ void ItemList::_notification(int p_what) { } //ensure_selected_visible needs to be checked before we draw the list. - if (ensure_selected_visible && current >= 0 && current <= items.size()) { + if (ensure_selected_visible && current >= 0 && current < items.size()) { Rect2 r = items[current].rect_cache; int from = scroll_bar->get_value(); @@ -1456,7 +1456,7 @@ void ItemList::_bind_methods() { ClassDB::bind_method(D_METHOD("set_item_icon", "idx", "icon"), &ItemList::set_item_icon); ClassDB::bind_method(D_METHOD("get_item_icon", "idx"), &ItemList::get_item_icon); - ClassDB::bind_method(D_METHOD("set_item_icon_transposed", "idx", "rect"), &ItemList::set_item_icon_transposed); + ClassDB::bind_method(D_METHOD("set_item_icon_transposed", "idx", "transposed"), &ItemList::set_item_icon_transposed); ClassDB::bind_method(D_METHOD("is_item_icon_transposed", "idx"), &ItemList::is_item_icon_transposed); ClassDB::bind_method(D_METHOD("set_item_icon_region", "idx", "rect"), &ItemList::set_item_icon_region); @@ -1553,12 +1553,12 @@ void ItemList::_bind_methods() { 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_PROPERTY(PropertyInfo(Variant::BOOL, "allow_rmb_select"), "set_allow_rmb_select", "get_allow_rmb_select"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "max_text_lines"), "set_max_text_lines", "get_max_text_lines"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_text_lines", PROPERTY_HINT_RANGE, "1,10,1,or_greater"), "set_max_text_lines", "get_max_text_lines"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_height"), "set_auto_height", "has_auto_height"); ADD_GROUP("Columns", ""); - ADD_PROPERTY(PropertyInfo(Variant::INT, "max_columns"), "set_max_columns", "get_max_columns"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_columns", PROPERTY_HINT_RANGE, "0,10,1,or_greater"), "set_max_columns", "get_max_columns"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "same_column_width"), "set_same_column_width", "is_same_column_width"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_column_width"), "set_fixed_column_width", "get_fixed_column_width"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_column_width", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_fixed_column_width", "get_fixed_column_width"); ADD_GROUP("Icon", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "icon_mode", PROPERTY_HINT_ENUM, "Top,Left"), "set_icon_mode", "get_icon_mode"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "icon_scale"), "set_icon_scale", "get_icon_scale"); diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h index 3a7cc65ab4..d9b510c762 100644 --- a/scene/gui/item_list.h +++ b/scene/gui/item_list.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index 9e2cd9e941..9b542cb179 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -35,9 +35,17 @@ void Label::set_autowrap(bool p_autowrap) { + if (autowrap == p_autowrap) { + return; + } + autowrap = p_autowrap; word_cache_dirty = true; update(); + + if (clip) { + minimum_size_changed(); + } } bool Label::has_autowrap() const { @@ -103,8 +111,7 @@ void Label::_notification(int p_what) { int lines_visible = (size.y + line_spacing) / font_h; - // ceiling to ensure autowrapping does not cut text - int space_w = Math::ceil(font->get_char_size(' ').width); + real_t space_w = font->get_char_size(' ').width; int chars_total = 0; int vbegin = 0, vsep = 0; @@ -313,8 +320,8 @@ Size2 Label::get_minimum_size() const { int Label::get_longest_line_width() const { Ref<Font> font = get_font("font"); - int max_line_width = 0; - int line_width = 0; + real_t max_line_width = 0; + real_t line_width = 0; for (int i = 0; i < xl_text.size(); i++) { @@ -332,8 +339,7 @@ int Label::get_longest_line_width() const { } } else { - // ceiling to ensure autowrapping does not cut text - int char_width = Math::ceil(font->get_char_size(current, xl_text[i + 1]).width); + real_t char_width = font->get_char_size(current, xl_text[i + 1]).width; line_width += char_width; } } @@ -341,7 +347,8 @@ int Label::get_longest_line_width() const { if (line_width > max_line_width) max_line_width = line_width; - return max_line_width; + // ceiling to ensure autowrapping does not cut text + return Math::ceil(max_line_width); } int Label::get_line_count() const { @@ -388,12 +395,11 @@ void Label::regenerate_word_cache() { Ref<Font> font = get_font("font"); - int current_word_size = 0; + real_t current_word_size = 0; int word_pos = 0; - int line_width = 0; + real_t line_width = 0; int space_count = 0; - // ceiling to ensure autowrapping does not cut text - int space_width = Math::ceil(font->get_char_size(' ').width); + real_t space_width = font->get_char_size(' ').width; int line_spacing = get_constant("line_spacing"); line_count = 1; total_char_cache = 0; @@ -413,7 +419,7 @@ void Label::regenerate_word_cache() { bool separatable = (current >= 0x2E08 && current <= 0xFAFF) || (current >= 0xFE30 && current <= 0xFE4F); //current>=33 && (current < 65||current >90) && (current<97||current>122) && (current<48||current>57); bool insert_newline = false; - int char_width = 0; + real_t char_width = 0; if (current < 33) { @@ -454,8 +460,7 @@ void Label::regenerate_word_cache() { if (current_word_size == 0) { word_pos = i; } - // ceiling to ensure autowrapping does not cut text - char_width = Math::ceil(font->get_char_size(current, xl_text[i + 1]).width); + char_width = font->get_char_size(current, xl_text[i + 1]).width; current_word_size += char_width; line_width += char_width; total_char_cache++; diff --git a/scene/gui/label.h b/scene/gui/label.h index 2cc55a47ef..ba6e627c58 100644 --- a/scene/gui/label.h +++ b/scene/gui/label.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index ab6f80bfa9..2504989d2c 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -128,7 +128,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { selection.doubleclick = false; if (OS::get_singleton()->has_virtual_keyboard()) - OS::get_singleton()->show_virtual_keyboard(text, get_global_rect()); + OS::get_singleton()->show_virtual_keyboard(text, get_global_rect(), max_length); } update(); @@ -184,6 +184,12 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { case KEY_H: { remap_key = KEY_BACKSPACE; } break; + case KEY_A: { + remap_key = KEY_HOME; + } break; + case KEY_E: { + remap_key = KEY_END; + } break; } if (remap_key != KEY_UNKNOWN) { @@ -240,15 +246,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { deselect(); text = text.substr(cursor_pos, text.length() - cursor_pos); - - Ref<Font> font = get_font("font"); - - cached_width = 0; - if (font != NULL) { - for (int i = 0; i < text.length(); i++) - cached_width += font->get_char_size(text[i]).width; - } - + update_cached_width(); set_cursor_position(0); _text_changed(); } @@ -557,8 +555,11 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { if (editable) { selection_delete(); CharType ucodestr[2] = { (CharType)k->get_unicode(), 0 }; + int prev_len = text.length(); append_at_cursor(ucodestr); - _text_changed(); + if (text.length() != prev_len) { + _text_changed(); + } accept_event(); } @@ -704,7 +705,7 @@ void LineEdit::_notification(int p_what) { } int x_ofs = 0; - bool using_placeholder = text.empty(); + bool using_placeholder = text.empty() && ime_text.empty(); int cached_text_width = using_placeholder ? cached_placeholder_width : cached_width; switch (align) { @@ -823,7 +824,7 @@ void LineEdit::_notification(int p_what) { 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 (char_ofs == cursor_pos && draw_caret && !using_placeholder) { if (ime_text.length() == 0) { #ifdef TOOLS_ENABLED VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs), Size2(Math::round(EDSCALE), caret_height)), cursor_color); @@ -866,12 +867,27 @@ void LineEdit::_notification(int p_what) { } } - if (char_ofs == cursor_pos && draw_caret) { // May be at the end. + if ((char_ofs == cursor_pos || using_placeholder) && draw_caret) { // May be at the end, or placeholder. if (ime_text.length() == 0) { + int caret_x_ofs = x_ofs; + if (using_placeholder) { + switch (align) { + case ALIGN_LEFT: + case ALIGN_FILL: { + caret_x_ofs = style->get_offset().x; + } break; + case ALIGN_CENTER: { + caret_x_ofs = ofs_max / 2; + } break; + case ALIGN_RIGHT: { + caret_x_ofs = ofs_max; + } break; + } + } #ifdef TOOLS_ENABLED - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs), Size2(Math::round(EDSCALE), caret_height)), cursor_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(caret_x_ofs, y_ofs), Size2(Math::round(EDSCALE), caret_height)), cursor_color); #else - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs), Size2(1, caret_height)), cursor_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(caret_x_ofs, y_ofs), Size2(1, caret_height)), cursor_color); #endif } } @@ -895,7 +911,7 @@ void LineEdit::_notification(int p_what) { OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos); if (OS::get_singleton()->has_virtual_keyboard()) - OS::get_singleton()->show_virtual_keyboard(text, get_global_rect()); + OS::get_singleton()->show_virtual_keyboard(text, get_global_rect(), max_length); } break; case NOTIFICATION_FOCUS_EXIT: { @@ -946,11 +962,12 @@ void LineEdit::paste_text() { if (paste_buffer != "") { + int prev_len = text.length(); if (selection.enabled) selection_delete(); append_at_cursor(paste_buffer); if (!text_changed_dirty) { - if (is_inside_tree()) { + if (is_inside_tree() && text.length() != prev_len) { MessageQueue::get_singleton()->push_call(this, "_text_changed"); } text_changed_dirty = true; @@ -970,6 +987,8 @@ void LineEdit::undo() { undo_stack_pos = undo_stack_pos->prev(); TextOperation op = undo_stack_pos->get(); text = op.text; + cached_width = op.cached_width; + window_pos = op.window_pos; set_cursor_position(op.cursor_pos); if (expand_to_text_length) @@ -988,6 +1007,8 @@ void LineEdit::redo() { undo_stack_pos = undo_stack_pos->next(); TextOperation op = undo_stack_pos->get(); text = op.text; + cached_width = op.cached_width; + window_pos = op.window_pos; set_cursor_position(op.cursor_pos); if (expand_to_text_length) @@ -1169,6 +1190,10 @@ void LineEdit::delete_char() { set_cursor_position(get_cursor_position() - 1); + if (align == ALIGN_CENTER || align == ALIGN_RIGHT) { + window_pos = CLAMP(window_pos - 1, 0, MAX(text.length() - 1, 0)); + } + _text_changed(); } @@ -1196,6 +1221,10 @@ void LineEdit::delete_text(int p_from_column, int p_to_column) { window_pos = cursor_pos; } + if (align == ALIGN_CENTER || align == ALIGN_RIGHT) { + window_pos = CLAMP(window_pos - (p_to_column - p_from_column), 0, MAX(text.length() - 1, 0)); + } + if (!text_changed_dirty) { if (is_inside_tree()) { MessageQueue::get_singleton()->push_call(this, "_text_changed"); @@ -1208,6 +1237,11 @@ void LineEdit::set_text(String p_text) { clear_internal(); append_at_cursor(p_text); + + if (expand_to_text_length) { + minimum_size_changed(); + } + update(); cursor_pos = 0; window_pos = 0; @@ -1322,19 +1356,13 @@ void LineEdit::set_window_pos(int p_pos) { void LineEdit::append_at_cursor(String p_text) { if ((max_length <= 0) || (text.length() + p_text.length() <= max_length)) { - - Ref<Font> font = get_font("font"); - if (font != NULL) { - for (int i = 0; i < p_text.length(); i++) - cached_width += font->get_char_size(p_text[i]).width; - } else { - cached_width = 0; - } - String pre = text.substr(0, cursor_pos); String post = text.substr(cursor_pos, text.length() - cursor_pos); text = pre + p_text + post; + update_cached_width(); set_cursor_position(cursor_pos + p_text.length()); + } else { + emit_signal("text_change_rejected"); } } @@ -1449,6 +1477,7 @@ void LineEdit::set_editable(bool p_editable) { editable = p_editable; _generate_context_menu(); + minimum_size_changed(); update(); } @@ -1460,6 +1489,7 @@ bool LineEdit::is_editable() const { void LineEdit::set_secret(bool p_secret) { pass = p_secret; + update_cached_width(); update(); } @@ -1475,6 +1505,7 @@ void LineEdit::set_secret_character(const String &p_string) { ERR_FAIL_COND_MSG(p_string.length() != 1, "Secret character must be exactly one character long (" + itos(p_string.length()) + " characters given)."); secret_character = p_string; + update_cached_width(); update(); } @@ -1584,7 +1615,11 @@ bool LineEdit::get_expand_to_text_length() const { } void LineEdit::set_clear_button_enabled(bool p_enabled) { + if (clear_button_enabled == p_enabled) { + return; + } clear_button_enabled = p_enabled; + minimum_size_changed(); update(); } @@ -1620,6 +1655,7 @@ void LineEdit::set_right_icon(const Ref<Texture> &p_icon) { return; } right_icon = p_icon; + minimum_size_changed(); update(); } @@ -1641,6 +1677,17 @@ void LineEdit::_emit_text_change() { text_changed_dirty = false; } +void LineEdit::update_cached_width() { + Ref<Font> font = get_font("font"); + cached_width = 0; + if (font != NULL) { + String text = get_text(); + for (int i = 0; i < text.length(); i++) { + cached_width += font->get_char_size(pass ? secret_character[0] : text[i]).width; + } + } +} + void LineEdit::update_placeholder_width() { if ((max_length <= 0) || (placeholder_translated.length() <= max_length)) { Ref<Font> font = get_font("font"); @@ -1677,7 +1724,9 @@ void LineEdit::_clear_undo_stack() { void LineEdit::_create_undo_state() { TextOperation op; op.text = text; + op.cached_width = cached_width; op.cursor_pos = cursor_pos; + op.window_pos = window_pos; undo_stack.push_back(op); } @@ -1752,6 +1801,7 @@ void LineEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("get_right_icon"), &LineEdit::get_right_icon); ADD_SIGNAL(MethodInfo("text_changed", PropertyInfo(Variant::STRING, "new_text"))); + ADD_SIGNAL(MethodInfo("text_change_rejected")); ADD_SIGNAL(MethodInfo("text_entered", PropertyInfo(Variant::STRING, "new_text"))); BIND_ENUM_CONSTANT(ALIGN_LEFT); diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 3424131dad..037238d682 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -106,6 +106,8 @@ private: struct TextOperation { int cursor_pos; + int window_pos; + int cached_width; String text; }; List<TextOperation> undo_stack; @@ -130,6 +132,7 @@ private: void _emit_text_change(); bool expand_to_text_length; + void update_cached_width(); void update_placeholder_width(); bool caret_blink_enabled; diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp index 21527e9bfc..4b8054bac6 100644 --- a/scene/gui/link_button.cpp +++ b/scene/gui/link_button.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/link_button.h b/scene/gui/link_button.h index 17c4bca67b..3bef25e249 100644 --- a/scene/gui/link_button.h +++ b/scene/gui/link_button.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/margin_container.cpp b/scene/gui/margin_container.cpp index 62ba45c484..53373fc297 100644 --- a/scene/gui/margin_container.cpp +++ b/scene/gui/margin_container.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/margin_container.h b/scene/gui/margin_container.h index 336b68665f..2fa41ecb6b 100644 --- a/scene/gui/margin_container.h +++ b/scene/gui/margin_container.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index e12cd55e6f..6e348054e2 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/menu_button.h b/scene/gui/menu_button.h index 5448ff13f2..9abd11632f 100644 --- a/scene/gui/menu_button.h +++ b/scene/gui/menu_button.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/nine_patch_rect.cpp b/scene/gui/nine_patch_rect.cpp index 23e0ea876d..945d1850d7 100644 --- a/scene/gui/nine_patch_rect.cpp +++ b/scene/gui/nine_patch_rect.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/nine_patch_rect.h b/scene/gui/nine_patch_rect.h index f31a09a482..3329c0a64c 100644 --- a/scene/gui/nine_patch_rect.h +++ b/scene/gui/nine_patch_rect.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index de8df4215d..3f46afa8e8 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -35,8 +35,16 @@ Size2 OptionButton::get_minimum_size() const { Size2 minsize = Button::get_minimum_size(); - if (has_icon("arrow")) - minsize.width += Control::get_icon("arrow")->get_width() + get_constant("hseparation"); + if (has_icon("arrow")) { + const Size2 padding = get_stylebox("normal")->get_minimum_size(); + const Size2 arrow_size = Control::get_icon("arrow")->get_size(); + + Size2 content_size = minsize - padding; + content_size.width += arrow_size.width + get_constant("hseparation"); + content_size.height = MAX(content_size.height, arrow_size.height); + + minsize = content_size + padding; + } return minsize; } @@ -73,6 +81,12 @@ void OptionButton::_notification(int p_what) { Point2 ofs(size.width - arrow->get_width() - get_constant("arrow_margin"), int(Math::abs((size.height - arrow->get_height()) / 2))); arrow->draw(ci, ofs, clr); } break; + case NOTIFICATION_THEME_CHANGED: { + + if (has_icon("arrow")) { + _set_internal_margin(MARGIN_RIGHT, Control::get_icon("arrow")->get_width()); + } + } break; case NOTIFICATION_VISIBILITY_CHANGED: { if (!is_visible_in_tree()) { @@ -327,7 +341,7 @@ void OptionButton::_bind_methods() { ClassDB::bind_method(D_METHOD("_get_items"), &OptionButton::_get_items); 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 + // "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"))); ADD_SIGNAL(MethodInfo("item_focused", PropertyInfo(Variant::INT, "id"))); @@ -339,6 +353,9 @@ OptionButton::OptionButton() { set_toggle_mode(true); set_text_align(ALIGN_LEFT); set_action_mode(ACTION_MODE_BUTTON_PRESS); + if (has_icon("arrow")) { + _set_internal_margin(MARGIN_RIGHT, Control::get_icon("arrow")->get_width()); + } popup = memnew(PopupMenu); popup->hide(); diff --git a/scene/gui/option_button.h b/scene/gui/option_button.h index 7210708042..04bd28fe28 100644 --- a/scene/gui/option_button.h +++ b/scene/gui/option_button.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/panel.cpp b/scene/gui/panel.cpp index c26bd09f50..0356607071 100644 --- a/scene/gui/panel.cpp +++ b/scene/gui/panel.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -42,7 +42,7 @@ void Panel::_notification(int p_what) { } Panel::Panel() { - + // Has visible stylebox, so stop by default. set_mouse_filter(MOUSE_FILTER_STOP); } diff --git a/scene/gui/panel.h b/scene/gui/panel.h index 84bf6e75f5..3538126d22 100644 --- a/scene/gui/panel.h +++ b/scene/gui/panel.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/panel_container.cpp b/scene/gui/panel_container.cpp index b1fced87fc..6cf23b8a32 100644 --- a/scene/gui/panel_container.cpp +++ b/scene/gui/panel_container.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -103,4 +103,6 @@ void PanelContainer::_notification(int p_what) { } PanelContainer::PanelContainer() { + // Has visible stylebox, so stop by default. + set_mouse_filter(MOUSE_FILTER_STOP); } diff --git a/scene/gui/panel_container.h b/scene/gui/panel_container.h index 15661d3e35..5623c3484b 100644 --- a/scene/gui/panel_container.h +++ b/scene/gui/panel_container.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index 32380b6457..64ef4a01f6 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/popup.h b/scene/gui/popup.h index 925760984e..ff472170b3 100644 --- a/scene/gui/popup.h +++ b/scene/gui/popup.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 08faaf7d45..87f17838cf 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -191,16 +191,20 @@ void PopupMenu::_submenu_timeout() { void PopupMenu::_scroll(float p_factor, const Point2 &p_over) { - const float global_y = get_global_position().y; - int vseparation = get_constant("vseparation"); Ref<Font> font = get_font("font"); float dy = (vseparation + font->get_height()) * 3 * p_factor * get_global_transform().get_scale().y; - if (dy > 0 && global_y < 0) - dy = MIN(dy, -global_y - 1); - else if (dy < 0 && global_y + get_size().y * get_global_transform().get_scale().y > get_viewport_rect().size.y) - dy = -MIN(-dy, global_y + get_size().y * get_global_transform().get_scale().y - get_viewport_rect().size.y - 1); + if (dy > 0) { + const float global_top = get_global_position().y; + const float limit = global_top < 0 ? -global_top : 0; + dy = MIN(dy, limit); + } else if (dy < 0) { + const float global_bottom = get_global_position().y + get_size().y * get_global_transform().get_scale().y; + const float viewport_height = get_viewport_rect().size.y; + const float limit = global_bottom > viewport_height ? global_bottom - viewport_height : 0; + dy = -MIN(-dy, limit); + } set_position(get_position() + Vector2(0, dy)); Ref<InputEventMouseMotion> ie; @@ -305,6 +309,7 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) { bool was_during_grabbed_click = during_grabbed_click; during_grabbed_click = false; + initial_button_mask = 0; int over = _get_mouse_over(b->get_position()); diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index 8c33178b09..f77ede0a8b 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/progress_bar.cpp b/scene/gui/progress_bar.cpp index 0154a452ad..e11295d7e7 100644 --- a/scene/gui/progress_bar.cpp +++ b/scene/gui/progress_bar.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/progress_bar.h b/scene/gui/progress_bar.h index 6157183e0f..371d0370f6 100644 --- a/scene/gui/progress_bar.h +++ b/scene/gui/progress_bar.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp index 9c016b5a50..6b6f5bca93 100644 --- a/scene/gui/range.cpp +++ b/scene/gui/range.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -100,7 +100,6 @@ void Range::set_value(double p_val) { shared->emit_value_changed(); } void Range::set_min(double p_min) { - shared->min = p_min; set_value(shared->val); @@ -109,7 +108,6 @@ void Range::set_min(double p_min) { update_configuration_warning(); } void Range::set_max(double p_max) { - shared->max = p_max; set_value(shared->val); @@ -173,6 +171,8 @@ void Range::set_as_ratio(double p_value) { } double Range::get_as_ratio() const { + ERR_FAIL_COND_V_MSG(Math::is_equal_approx(get_max(), get_min()), 0.0, "Cannot get ratio when minimum and maximum value are equal."); + if (shared->exp_ratio && get_min() >= 0) { double exp_min = get_min() == 0 ? 0.0 : Math::log(get_min()) / Math::log((double)2); diff --git a/scene/gui/range.h b/scene/gui/range.h index 8ce450f8fc..819d76941b 100644 --- a/scene/gui/range.h +++ b/scene/gui/range.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/reference_rect.cpp b/scene/gui/reference_rect.cpp index 052c8ccd05..0765e5d882 100644 --- a/scene/gui/reference_rect.cpp +++ b/scene/gui/reference_rect.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/reference_rect.h b/scene/gui/reference_rect.h index 7a88333cf2..c25c54f271 100644 --- a/scene/gui/reference_rect.h +++ b/scene/gui/reference_rect.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/rich_text_effect.cpp b/scene/gui/rich_text_effect.cpp index f9e0be5b31..c5b1685ff9 100644 --- a/scene/gui/rich_text_effect.cpp +++ b/scene/gui/rich_text_effect.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -89,8 +89,6 @@ void CharFXTransform::_bind_methods() { ClassDB::bind_method(D_METHOD("get_character"), &CharFXTransform::get_character); ClassDB::bind_method(D_METHOD("set_character", "character"), &CharFXTransform::set_character); - ClassDB::bind_method(D_METHOD("get_value_or", "key", "default_value"), &CharFXTransform::get_value_or); - ADD_PROPERTY(PropertyInfo(Variant::INT, "relative_index"), "set_relative_index", "get_relative_index"); ADD_PROPERTY(PropertyInfo(Variant::INT, "absolute_index"), "set_absolute_index", "get_absolute_index"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "elapsed_time"), "set_elapsed_time", "get_elapsed_time"); @@ -101,17 +99,6 @@ void CharFXTransform::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "character"), "set_character", "get_character"); } -Variant CharFXTransform::get_value_or(String p_key, Variant p_default_value) { - if (!this->environment.has(p_key)) - return p_default_value; - - Variant r = environment[p_key]; - if (r.get_type() != p_default_value.get_type()) - return p_default_value; - - return r; -} - CharFXTransform::CharFXTransform() { relative_index = 0; absolute_index = 0; diff --git a/scene/gui/rich_text_effect.h b/scene/gui/rich_text_effect.h index 4330cebfe6..77c82aa780 100644 --- a/scene/gui/rich_text_effect.h +++ b/scene/gui/rich_text_effect.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -82,8 +82,6 @@ public: void set_character(int p_char) { character = (CharType)p_char; } Dictionary get_environment() { return environment; } void set_environment(Dictionary p_environment) { environment = p_environment; } - - Variant get_value_or(String p_key, Variant p_default_value); }; #endif // RICH_TEXT_EFFECT_H diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 0331046492..b19e1d8362 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,8 +33,13 @@ #include "core/math/math_defs.h" #include "core/os/keyboard.h" #include "core/os/os.h" -#include "modules/regex/regex.h" #include "scene/scene_string_names.h" + +#include "modules/modules_enabled.gen.h" +#ifdef MODULE_REGEX_ENABLED +#include "modules/regex/regex.h" +#endif + #ifdef TOOLS_ENABLED #include "editor/editor_scale.h" #endif @@ -199,6 +204,8 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & int line_ascent = cfont->get_ascent(); int line_descent = cfont->get_descent(); + int backtrack = 0; // for dynamic hidden content. + int nonblank_line_count = 0; //number of nonblank lines as counted during PROCESS_DRAW Variant meta; @@ -209,6 +216,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & { \ if (p_mode != PROCESS_CACHE) { \ line++; \ + backtrack = 0; \ if (!line_is_blank) { \ nonblank_line_count++; \ } \ @@ -253,24 +261,25 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & } \ } -#define ENSURE_WIDTH(m_width) \ - if (p_mode == PROCESS_CACHE) { \ - l.maximum_width = MAX(l.maximum_width, MIN(p_width, wofs + m_width)); \ - l.minimum_width = MAX(l.minimum_width, m_width); \ - } \ - if (wofs + m_width > p_width) { \ - line_wrapped = true; \ - if (p_mode == PROCESS_CACHE) { \ - if (spaces > 0) \ - spaces -= 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; \ - *r_click_item = it; \ - *r_click_char = rchar; \ - RETURN; \ - } \ - NEW_LINE \ +#define ENSURE_WIDTH(m_width) \ + if (p_mode == PROCESS_CACHE) { \ + l.maximum_width = MAX(l.maximum_width, MIN(p_width, wofs + m_width)); \ + l.minimum_width = MAX(l.minimum_width, m_width); \ + } \ + if (wofs - backtrack + m_width > p_width) { \ + line_wrapped = true; \ + if (p_mode == PROCESS_CACHE) { \ + if (spaces > 0) \ + spaces -= 1; \ + } \ + const bool x_in_range = (p_click_pos.x > p_ofs.x + wofs) && (!p_frame->cell || p_click_pos.x < p_ofs.x + p_width); \ + 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 && x_in_range) { \ + if (r_outside) *r_outside = true; \ + *r_click_item = it; \ + *r_click_char = rchar; \ + RETURN; \ + } \ + NEW_LINE \ } #define ADVANCE(m_width) \ @@ -384,6 +393,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & int fw = 0; 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; @@ -426,13 +436,12 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & { - int ofs = 0; + int ofs = 0 - backtrack; for (int i = 0; i < end; i++) { int pofs = wofs + ofs; if (p_mode == PROCESS_POINTER && r_click_char && p_click_pos.y >= p_ofs.y + y && p_click_pos.y <= p_ofs.y + y + lh) { - //int o = (wofs+w)-p_click_pos.x; int cw = font->get_char_size(c[i], c[i + 1]).x; @@ -475,7 +484,10 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & bool visible = visible_characters < 0 || ((p_char_count < visible_characters && YRANGE_VISIBLE(y + lh - line_descent - line_ascent, line_ascent + line_descent)) && faded_visibility > 0.0f); + const bool previously_visible = visible; + for (int j = 0; j < fx_stack.size(); j++) { + ItemFX *item_fx = fx_stack[j]; if (item_fx->type == ITEM_CUSTOMFX && custom_fx_ok) { @@ -569,6 +581,8 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & } else { cw = drawer.draw_char(ci, p_ofs + Point2(align_ofs + pofs, y + lh - line_descent) + fx_offset, fx_char, c[i + 1], fx_color); } + } else if (previously_visible) { + backtrack += font->get_char_size(fx_char, c[i + 1]).x; } p_char_count++; @@ -642,6 +656,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & case ITEM_NEWLINE: { lh = 0; + if (p_mode != PROCESS_CACHE) { lh = line < l.height_caches.size() ? l.height_caches[line] : 1; line_is_blank = true; @@ -934,6 +949,14 @@ void RichTextLabel::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_MOUSE_EXIT: { + if (meta_hovering) { + meta_hovering = NULL; + emit_signal("meta_hover_ended", current_meta); + current_meta = false; + update(); + } + } break; case NOTIFICATION_RESIZED: { main->first_invalid_line = 0; //invalidate ALL @@ -1063,10 +1086,10 @@ Control::CursorShape RichTextLabel::get_cursor_shape(const Point2 &p_pos) const int line = 0; Item *item = NULL; + bool outside; + ((RichTextLabel *)(this))->_find_click(main, p_pos, &item, &line, &outside); - ((RichTextLabel *)(this))->_find_click(main, p_pos, &item, &line); - - if (item && ((RichTextLabel *)(this))->_find_meta(item, NULL)) + if (item && !outside && ((RichTextLabel *)(this))->_find_meta(item, NULL)) return CURSOR_POINTING_HAND; return CURSOR_ARROW; @@ -1701,6 +1724,9 @@ bool RichTextLabel::remove_line(const int p_line) { if (!was_newline) { current_frame->lines.remove(p_line); + if (current_frame->lines.size() == 0) { + current_frame->lines.resize(1); + } } if (p_line == 0 && current->subitems.size() > 0) @@ -2852,6 +2878,7 @@ Dictionary RichTextLabel::parse_expressions_for_values(Vector<String> p_expressi Vector<String> values = parts[1].split(",", false); +#ifdef MODULE_REGEX_ENABLED RegEx color = RegEx(); color.compile("^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$"); RegEx nodepath = RegEx(); @@ -2885,6 +2912,7 @@ Dictionary RichTextLabel::parse_expressions_for_values(Vector<String> p_expressi a.append(values[j]); } } +#endif if (values.size() > 1) { d[key] = a; diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index b9837fdfcc..61ac0bd86c 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp index a7c15151ae..45fa212886 100644 --- a/scene/gui/scroll_bar.cpp +++ b/scene/gui/scroll_bar.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/scroll_bar.h b/scene/gui/scroll_bar.h index cbcee1dae3..ee5e7140cf 100644 --- a/scene/gui/scroll_bar.h +++ b/scene/gui/scroll_bar.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index a840e3fec1..509e6d19f6 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,6 +30,7 @@ #include "scroll_container.h" #include "core/os/os.h" +#include "scene/main/viewport.h" bool ScrollContainer::clips_input() const { @@ -218,20 +219,45 @@ void ScrollContainer::_update_scrollbar_position() { Size2 hmin = h_scroll->get_combined_minimum_size(); Size2 vmin = v_scroll->get_combined_minimum_size(); - v_scroll->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -vmin.width); - v_scroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0); - v_scroll->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 0); - v_scroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0); - h_scroll->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 0); h_scroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0); h_scroll->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, -hmin.height); h_scroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0); + v_scroll->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -vmin.width); + v_scroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0); + v_scroll->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 0); + v_scroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0); + h_scroll->raise(); v_scroll->raise(); } +void ScrollContainer::_ensure_focused_visible(Control *p_control) { + + if (!follow_focus) { + return; + } + + if (is_a_parent_of(p_control)) { + Rect2 global_rect = get_global_rect(); + Rect2 other_rect = p_control->get_global_rect(); + float right_margin = 0; + if (v_scroll->is_visible()) { + right_margin += v_scroll->get_size().x; + } + float bottom_margin = 0; + if (h_scroll->is_visible()) { + bottom_margin += h_scroll->get_size().y; + } + + float diff = MAX(MIN(other_rect.position.y, global_rect.position.y), other_rect.position.y + other_rect.size.y - global_rect.size.y + bottom_margin); + set_v_scroll(get_v_scroll() + (diff - global_rect.position.y)); + diff = MAX(MIN(other_rect.position.x, global_rect.position.x), other_rect.position.x + other_rect.size.x - global_rect.size.x + right_margin); + set_h_scroll(get_h_scroll() + (diff - global_rect.position.x)); + } +} + void ScrollContainer::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { @@ -239,6 +265,11 @@ void ScrollContainer::_notification(int p_what) { call_deferred("_update_scrollbar_position"); }; + if (p_what == NOTIFICATION_READY) { + + get_viewport()->connect("gui_focus_changed", this, "_ensure_focused_visible"); + } + if (p_what == NOTIFICATION_SORT_CHILDREN) { child_max_size = Size2(0, 0); @@ -286,6 +317,7 @@ void ScrollContainer::_notification(int p_what) { r.position += ofs; fit_child_in_rect(c, r); } + update(); }; @@ -377,18 +409,21 @@ void ScrollContainer::update_scrollbars() { Size2 hmin; Size2 vmin; - if (scroll_h) hmin = h_scroll->get_combined_minimum_size(); - if (scroll_v) vmin = v_scroll->get_combined_minimum_size(); + if (scroll_h) { + hmin = h_scroll->get_combined_minimum_size(); + } + if (scroll_v) { + vmin = v_scroll->get_combined_minimum_size(); + } Size2 min = child_max_size; - bool hide_scroll_v = !scroll_v || min.height <= size.height - hmin.height; - bool hide_scroll_h = !scroll_h || min.width <= size.width - vmin.width; + bool hide_scroll_v = !scroll_v || min.height <= size.height; + bool hide_scroll_h = !scroll_h || min.width <= size.width; if (hide_scroll_v) { v_scroll->hide(); - v_scroll->set_max(0); scroll.y = 0; } else { @@ -406,7 +441,6 @@ void ScrollContainer::update_scrollbars() { if (hide_scroll_h) { h_scroll->hide(); - h_scroll->set_max(0); scroll.x = 0; } else { @@ -420,6 +454,10 @@ void ScrollContainer::update_scrollbars() { scroll.x = h_scroll->get_value(); } + + // Avoid scrollbar overlapping. + h_scroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, hide_scroll_v ? 0 : -vmin.width); + v_scroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, hide_scroll_h ? 0 : -hmin.height); } void ScrollContainer::_scroll_moved(float) { @@ -432,8 +470,12 @@ void ScrollContainer::_scroll_moved(float) { }; void ScrollContainer::set_enable_h_scroll(bool p_enable) { + if (scroll_h == p_enable) { + return; + } scroll_h = p_enable; + minimum_size_changed(); queue_sort(); } @@ -443,8 +485,12 @@ bool ScrollContainer::is_h_scroll_enabled() const { } void ScrollContainer::set_enable_v_scroll(bool p_enable) { + if (scroll_v == p_enable) { + return; + } scroll_v = p_enable; + minimum_size_changed(); queue_sort(); } @@ -481,6 +527,14 @@ void ScrollContainer::set_deadzone(int p_deadzone) { deadzone = p_deadzone; } +bool ScrollContainer::is_following_focus() const { + return follow_focus; +} + +void ScrollContainer::set_follow_focus(bool p_follow) { + follow_focus = p_follow; +} + String ScrollContainer::get_configuration_warning() const { int found = 0; @@ -523,12 +577,15 @@ void ScrollContainer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_enable_v_scroll", "enable"), &ScrollContainer::set_enable_v_scroll); ClassDB::bind_method(D_METHOD("is_v_scroll_enabled"), &ScrollContainer::is_v_scroll_enabled); ClassDB::bind_method(D_METHOD("_update_scrollbar_position"), &ScrollContainer::_update_scrollbar_position); + ClassDB::bind_method(D_METHOD("_ensure_focused_visible"), &ScrollContainer::_ensure_focused_visible); ClassDB::bind_method(D_METHOD("set_h_scroll", "value"), &ScrollContainer::set_h_scroll); ClassDB::bind_method(D_METHOD("get_h_scroll"), &ScrollContainer::get_h_scroll); ClassDB::bind_method(D_METHOD("set_v_scroll", "value"), &ScrollContainer::set_v_scroll); ClassDB::bind_method(D_METHOD("get_v_scroll"), &ScrollContainer::get_v_scroll); ClassDB::bind_method(D_METHOD("set_deadzone", "deadzone"), &ScrollContainer::set_deadzone); ClassDB::bind_method(D_METHOD("get_deadzone"), &ScrollContainer::get_deadzone); + ClassDB::bind_method(D_METHOD("set_follow_focus", "enabled"), &ScrollContainer::set_follow_focus); + ClassDB::bind_method(D_METHOD("is_following_focus"), &ScrollContainer::is_following_focus); ClassDB::bind_method(D_METHOD("get_h_scrollbar"), &ScrollContainer::get_h_scrollbar); ClassDB::bind_method(D_METHOD("get_v_scrollbar"), &ScrollContainer::get_v_scrollbar); @@ -536,6 +593,8 @@ void ScrollContainer::_bind_methods() { ADD_SIGNAL(MethodInfo("scroll_started")); ADD_SIGNAL(MethodInfo("scroll_ended")); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "follow_focus"), "set_follow_focus", "is_following_focus"); + ADD_GROUP("Scroll", "scroll_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_horizontal_enabled"), "set_enable_h_scroll", "is_h_scroll_enabled"); ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_horizontal"), "set_h_scroll", "get_h_scroll"); @@ -551,12 +610,11 @@ ScrollContainer::ScrollContainer() { h_scroll = memnew(HScrollBar); h_scroll->set_name("_h_scroll"); add_child(h_scroll); + h_scroll->connect("value_changed", this, "_scroll_moved"); v_scroll = memnew(VScrollBar); v_scroll->set_name("_v_scroll"); add_child(v_scroll); - - h_scroll->connect("value_changed", this, "_scroll_moved"); v_scroll->connect("value_changed", this, "_scroll_moved"); drag_speed = Vector2(); @@ -567,6 +625,7 @@ ScrollContainer::ScrollContainer() { scroll_v = true; deadzone = GLOBAL_GET("gui/common/default_scroll_deadzone"); + follow_focus = false; set_clip_contents(true); }; diff --git a/scene/gui/scroll_container.h b/scene/gui/scroll_container.h index 2ab169f4d0..6423b36fcc 100644 --- a/scene/gui/scroll_container.h +++ b/scene/gui/scroll_container.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -62,6 +62,7 @@ class ScrollContainer : public Container { bool scroll_v; int deadzone; + bool follow_focus; void _cancel_drag(); @@ -75,6 +76,7 @@ protected: static void _bind_methods(); void _update_scrollbar_position(); + void _ensure_focused_visible(Control *p_node); public: int get_v_scroll() const; @@ -92,6 +94,9 @@ public: int get_deadzone() const; void set_deadzone(int p_deadzone); + bool is_following_focus() const; + void set_follow_focus(bool p_follow); + HScrollBar *get_h_scrollbar(); VScrollBar *get_v_scrollbar(); diff --git a/scene/gui/separator.cpp b/scene/gui/separator.cpp index a717420b9b..4635efb233 100644 --- a/scene/gui/separator.cpp +++ b/scene/gui/separator.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/separator.h b/scene/gui/separator.h index 89039f3112..9a64d6ba99 100644 --- a/scene/gui/separator.h +++ b/scene/gui/separator.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/shortcut.cpp b/scene/gui/shortcut.cpp index 400fdca082..262d8076f3 100644 --- a/scene/gui/shortcut.cpp +++ b/scene/gui/shortcut.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/shortcut.h b/scene/gui/shortcut.h index df0623ed50..59d3245db5 100644 --- a/scene/gui/shortcut.h +++ b/scene/gui/shortcut.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp index ba57be1686..9b3ed35e6e 100644 --- a/scene/gui/slider.cpp +++ b/scene/gui/slider.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -166,7 +166,6 @@ void Slider::_notification(int p_what) { RID ci = get_canvas_item(); Size2i size = get_size(); Ref<StyleBox> style = get_stylebox("slider"); - Ref<StyleBox> focus = get_stylebox("focus"); Ref<StyleBox> grabber_area = get_stylebox("grabber_area"); Ref<Texture> grabber = get_icon(editable ? ((mouse_inside || has_focus()) ? "grabber_highlight" : "grabber") : "grabber_disabled"); Ref<Texture> tick = get_icon("tick"); @@ -178,10 +177,7 @@ void Slider::_notification(int p_what) { float areasize = size.height - grabber->get_size().height; style->draw(ci, Rect2i(Point2i(size.width / 2 - widget_width / 2, 0), Size2i(widget_width, size.height))); grabber_area->draw(ci, Rect2i(Point2i((size.width - widget_width) / 2, size.height - areasize * ratio - grabber->get_size().height / 2), Size2i(widget_width, areasize * ratio + grabber->get_size().width / 2))); - /* - if (mouse_inside||has_focus()) - focus->draw(ci,Rect2i(Point2i(),Size2i(style->get_minimum_size().width+style->get_center_size().width,size.height))); - */ + if (ticks > 1) { int grabber_offset = (grabber->get_size().height / 2 - tick->get_height() / 2); for (int i = 0; i < ticks; i++) { @@ -198,10 +194,6 @@ void Slider::_notification(int p_what) { style->draw(ci, Rect2i(Point2i(0, (size.height - widget_height) / 2), Size2i(size.width, widget_height))); grabber_area->draw(ci, Rect2i(Point2i(0, (size.height - widget_height) / 2), Size2i(areasize * ratio + grabber->get_size().width / 2, widget_height))); - /* - if (mouse_inside||has_focus()) - focus->draw(ci,Rect2i(Point2i(),Size2i(size.width,style->get_minimum_size().height+style->get_center_size().height))); - */ if (ticks > 1) { int grabber_offset = (grabber->get_size().width / 2 - tick->get_width() / 2); diff --git a/scene/gui/slider.h b/scene/gui/slider.h index d0ab7baecf..1248044ec4 100644 --- a/scene/gui/slider.h +++ b/scene/gui/slider.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index bf067898e6..92377949f8 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -211,6 +211,10 @@ void SpinBox::_notification(int p_what) { _adjust_width_for_icon(get_icon("updown")); _value_changed(0); + } else if (p_what == NOTIFICATION_THEME_CHANGED) { + + call_deferred("minimum_size_changed"); + get_line_edit()->call_deferred("minimum_size_changed"); } } @@ -255,6 +259,10 @@ bool SpinBox::is_editable() const { return line_edit->is_editable(); } +void SpinBox::apply() { + _text_entered(line_edit->get_text()); +} + void SpinBox::_bind_methods() { //ClassDB::bind_method(D_METHOD("_value_changed"),&SpinBox::_value_changed); @@ -268,6 +276,7 @@ void SpinBox::_bind_methods() { ClassDB::bind_method(D_METHOD("get_prefix"), &SpinBox::get_prefix); ClassDB::bind_method(D_METHOD("set_editable", "editable"), &SpinBox::set_editable); ClassDB::bind_method(D_METHOD("is_editable"), &SpinBox::is_editable); + ClassDB::bind_method(D_METHOD("apply"), &SpinBox::apply); ClassDB::bind_method(D_METHOD("_line_edit_focus_exit"), &SpinBox::_line_edit_focus_exit); ClassDB::bind_method(D_METHOD("get_line_edit"), &SpinBox::get_line_edit); ClassDB::bind_method(D_METHOD("_line_edit_input"), &SpinBox::_line_edit_input); diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h index 9cf977d2d6..04491c8477 100644 --- a/scene/gui/spin_box.h +++ b/scene/gui/spin_box.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -88,6 +88,8 @@ public: void set_prefix(const String &p_prefix); String get_prefix() const; + void apply(); + SpinBox(); }; diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp index e5d1844d39..079907db07 100644 --- a/scene/gui/split_container.cpp +++ b/scene/gui/split_container.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -266,7 +266,7 @@ void SplitContainer::_gui_input(const Ref<InputEvent> &p_event) { Control::CursorShape SplitContainer::get_cursor_shape(const Point2 &p_pos) const { if (dragging) - return (vertical ? CURSOR_VSIZE : CURSOR_HSIZE); + return (vertical ? CURSOR_VSPLIT : CURSOR_HSPLIT); if (!collapsed && _getch(0) && _getch(1) && dragger_visibility == DRAGGER_VISIBLE) { @@ -275,11 +275,11 @@ Control::CursorShape SplitContainer::get_cursor_shape(const Point2 &p_pos) const if (vertical) { if (p_pos.y > middle_sep && p_pos.y < middle_sep + sep) - return CURSOR_VSIZE; + return CURSOR_VSPLIT; } else { if (p_pos.x > middle_sep && p_pos.x < middle_sep + sep) - return CURSOR_HSIZE; + return CURSOR_HSPLIT; } } diff --git a/scene/gui/split_container.h b/scene/gui/split_container.h index 97838e19a3..d759c6ad35 100644 --- a/scene/gui/split_container.h +++ b/scene/gui/split_container.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index a29ba36bad..b045ff4fe1 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -785,23 +785,25 @@ TabContainer::TabAlign TabContainer::get_tab_align() const { return align; } -void TabContainer::set_tabs_visible(bool p_visibe) { +void TabContainer::set_tabs_visible(bool p_visible) { - if (p_visibe == tabs_visible) + if (p_visible == tabs_visible) return; - tabs_visible = p_visibe; + tabs_visible = p_visible; Vector<Control *> tabs = _get_tabs(); for (int i = 0; i < tabs.size(); i++) { Control *c = tabs[i]; - if (p_visibe) + if (p_visible) c->set_margin(MARGIN_TOP, _get_top_margin()); else c->set_margin(MARGIN_TOP, 0); } + update(); + minimum_size_changed(); } bool TabContainer::are_tabs_visible() const { @@ -936,8 +938,10 @@ Size2 TabContainer::get_minimum_size() const { Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled"); Ref<Font> font = get_font("font"); - ms.y += MAX(MAX(tab_bg->get_minimum_size().y, tab_fg->get_minimum_size().y), tab_disabled->get_minimum_size().y); - ms.y += font->get_height(); + if (tabs_visible) { + ms.y += MAX(MAX(tab_bg->get_minimum_size().y, tab_fg->get_minimum_size().y), tab_disabled->get_minimum_size().y); + ms.y += font->get_height(); + } Ref<StyleBox> sb = get_stylebox("panel"); ms += sb->get_minimum_size(); diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h index 0c17ebc3ae..c5a9045ca6 100644 --- a/scene/gui/tab_container.h +++ b/scene/gui/tab_container.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -87,7 +87,7 @@ public: void set_tab_align(TabAlign p_align); TabAlign get_tab_align() const; - void set_tabs_visible(bool p_visibe); + void set_tabs_visible(bool p_visible); bool are_tabs_visible() const; void set_tab_title(int p_tab, const String &p_title); diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp index c24f15384b..6cd95e73fc 100644 --- a/scene/gui/tabs.cpp +++ b/scene/gui/tabs.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/tabs.h b/scene/gui/tabs.h index 0edf2fedc1..c06e47a54a 100644 --- a/scene/gui/tabs.h +++ b/scene/gui/tabs.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 8ddc31745e..9d5e004ed3 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -417,7 +417,6 @@ void TextEdit::_update_scrollbars() { cursor.line_ofs = 0; cursor.wrap_ofs = 0; v_scroll->set_value(0); - v_scroll->set_max(0); v_scroll->hide(); } @@ -436,7 +435,6 @@ void TextEdit::_update_scrollbars() { cursor.x_ofs = 0; h_scroll->set_value(0); - h_scroll->set_max(0); h_scroll->hide(); } @@ -1948,6 +1946,7 @@ void TextEdit::indent_right() { // Ignore if the cursor is not past the first column. if (is_selection_active() && get_selection_to_column() == 0) { + selection_offset = 0; end_line--; } @@ -4440,7 +4439,6 @@ int TextEdit::get_line_wrap_index_at_col(int p_line, int p_column) const { } void TextEdit::cursor_set_column(int p_col, bool p_adjust_viewport) { - if (p_col < 0) p_col = 0; @@ -4482,7 +4480,7 @@ void TextEdit::cursor_set_line(int p_row, bool p_adjust_viewport, bool p_can_be_ if (p_row - move_up > 0 && !is_line_hidden(p_row - move_up)) { p_row -= move_up; } else { - WARN_PRINTS(("Cursor set to hidden line " + itos(p_row) + " and there are no nonhidden lines.")); + WARN_PRINT(("Cursor set to hidden line " + itos(p_row) + " and there are no nonhidden lines.")); } } } @@ -4593,6 +4591,7 @@ void TextEdit::_scroll_moved(double p_to_val) { break; } } + n_line = MIN(n_line, text.size() - 1); int line_wrap_amount = times_line_wraps(n_line); int wi = line_wrap_amount - (sc - v_scroll_i - 1); wi = CLAMP(wi, 0, line_wrap_amount); @@ -5179,11 +5178,16 @@ void TextEdit::cut() { OS::get_singleton()->set_clipboard(clipboard); cursor_set_line(cursor.line); cursor_set_column(0); - _remove_text(cursor.line, 0, cursor.line, text[cursor.line].length()); - backspace_at_cursor(); + if (cursor.line == 0 && get_line_count() > 1) { + _remove_text(cursor.line, 0, cursor.line + 1, 0); + } else { + _remove_text(cursor.line, 0, cursor.line, text[cursor.line].length()); + backspace_at_cursor(); + cursor_set_line(cursor.line + 1); + } + update(); - cursor_set_line(cursor.line + 1); cut_copy_line = clipboard; } else { @@ -6526,6 +6530,10 @@ void TextEdit::_update_completion_candidates() { Vector<float> sim_cache; bool single_quote = s.begins_with("'"); Vector<ScriptCodeCompletionOption> completion_options_casei; + Vector<ScriptCodeCompletionOption> completion_options_subseq; + Vector<ScriptCodeCompletionOption> completion_options_subseq_casei; + + String s_lower = s.to_lower(); for (List<ScriptCodeCompletionOption>::Element *E = completion_sources.front(); E; E = E->next()) { ScriptCodeCompletionOption &option = E->get(); @@ -6540,31 +6548,68 @@ void TextEdit::_update_completion_candidates() { option.insert_text = option.insert_text.quote(quote); } - if (option.display.begins_with(s)) { + if (option.display.length() == 0) { + continue; + } else if (s.length() == 0) { completion_options.push_back(option); - } else if (option.display.to_lower().begins_with(s.to_lower())) { - completion_options_casei.push_back(option); - } - } + } else { - completion_options.append_array(completion_options_casei); + // This code works the same as: + /* + if (option.display.begins_with(s)) { + completion_options.push_back(option); + } else if (option.display.to_lower().begins_with(s.to_lower())) { + completion_options_casei.push_back(option); + } else if (s.is_subsequence_of(option.display)) { + completion_options_subseq.push_back(option); + } else if (s.is_subsequence_ofi(option.display)) { + completion_options_subseq_casei.push_back(option); + } + */ + // But is more performant due to being inlined and looping over the characters only once - if (completion_options.size() == 0) { - for (int i = 0; i < completion_sources.size(); i++) { - if (s.is_subsequence_of(completion_sources[i].display)) { - completion_options.push_back(completion_sources[i]); + String display_lower = option.display.to_lower(); + + const CharType *ssq = &s[0]; + const CharType *ssq_lower = &s_lower[0]; + + const CharType *tgt = &option.display[0]; + const CharType *tgt_lower = &display_lower[0]; + + const CharType *ssq_last_tgt = NULL; + const CharType *ssq_lower_last_tgt = NULL; + + for (; *tgt; tgt++, tgt_lower++) { + if (*ssq == *tgt) { + ssq++; + ssq_last_tgt = tgt; + } + if (*ssq_lower == *tgt_lower) { + ssq_lower++; + ssq_lower_last_tgt = tgt; + } } - } - } - if (completion_options.size() == 0) { - for (int i = 0; i < completion_sources.size(); i++) { - if (s.is_subsequence_ofi(completion_sources[i].display)) { - completion_options.push_back(completion_sources[i]); + if (!*ssq) { // Matched the whole subsequence in s + if (ssq_last_tgt == &option.display[s.length() - 1]) { // Finished matching in the first s.length() characters + completion_options.push_back(option); + } else { + completion_options_subseq.push_back(option); + } + } else if (!*ssq_lower) { // Matched the whole subsequence in s_lower + if (ssq_lower_last_tgt == &option.display[s.length() - 1]) { // Finished matching in the first s.length() characters + completion_options_casei.push_back(option); + } else { + completion_options_subseq_casei.push_back(option); + } } } } + completion_options.append_array(completion_options_casei); + completion_options.append_array(completion_options_subseq); + completion_options.append_array(completion_options_subseq_casei); + if (completion_options.size() == 0) { // No options to complete, cancel. _cancel_completion(); @@ -7066,6 +7111,10 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("is_smooth_scroll_enabled"), &TextEdit::is_smooth_scroll_enabled); ClassDB::bind_method(D_METHOD("set_v_scroll_speed", "speed"), &TextEdit::set_v_scroll_speed); ClassDB::bind_method(D_METHOD("get_v_scroll_speed"), &TextEdit::get_v_scroll_speed); + ClassDB::bind_method(D_METHOD("set_v_scroll", "value"), &TextEdit::set_v_scroll); + ClassDB::bind_method(D_METHOD("get_v_scroll"), &TextEdit::get_v_scroll); + ClassDB::bind_method(D_METHOD("set_h_scroll", "value"), &TextEdit::set_h_scroll); + ClassDB::bind_method(D_METHOD("get_h_scroll"), &TextEdit::get_h_scroll); ClassDB::bind_method(D_METHOD("add_keyword_color", "keyword", "color"), &TextEdit::add_keyword_color); ClassDB::bind_method(D_METHOD("has_keyword_color", "keyword"), &TextEdit::has_keyword_color); @@ -7101,6 +7150,8 @@ void TextEdit::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "v_scroll_speed"), "set_v_scroll_speed", "get_v_scroll_speed"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hiding_enabled"), "set_hiding_enabled", "is_hiding_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "wrap_enabled"), "set_wrap_enabled", "is_wrap_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "scroll_vertical"), "set_v_scroll", "get_v_scroll"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_horizontal"), "set_h_scroll", "get_h_scroll"); ADD_GROUP("Minimap", "minimap_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "minimap_draw"), "draw_minimap", "is_drawing_minimap"); @@ -7142,6 +7193,7 @@ TextEdit::TextEdit() { max_chars = 0; clear(); wrap_enabled = false; + wrap_at = 0; wrap_right_offset = 10; set_focus_mode(FOCUS_ALL); syntax_highlighter = NULL; diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 594366de7d..b4e7dcfebb 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -69,6 +69,10 @@ public: int region; bool end; + ColorRegionInfo() { + region = 0; + end = false; + } }; struct Line { @@ -84,6 +88,16 @@ public: Ref<Texture> info_icon; String info; String data; + Line() { + width_cache = 0; + marked = false; + breakpoint = false; + bookmark = false; + hidden = false; + safe = false; + has_info = false; + wrap_amount_cache = 0; + } }; private: @@ -143,6 +157,14 @@ private: int last_fit_x; int line, column; ///< cursor int x_ofs, line_ofs, wrap_ofs; + Cursor() { + last_fit_x = 0; + line = 0; + column = 0; ///< cursor + x_ofs = 0; + line_ofs = 0; + wrap_ofs = 0; + } } cursor; struct Selection { @@ -167,7 +189,21 @@ private: int to_line, to_column; bool shiftclick_left; - + Selection() { + selecting_mode = MODE_NONE; + selecting_line = 0; + selecting_column = 0; + selected_word_beg = 0; + selected_word_end = 0; + selected_word_origin = 0; + selecting_text = false; + active = false; + from_line = 0; + from_column = 0; + to_line = 0; + to_column = 0; + shiftclick_left = false; + } } selection; struct Cache { @@ -219,6 +255,16 @@ private: int fold_gutter_width; int info_gutter_width; int minimap_width; + Cache() { + + row_height = 0; + line_spacing = 0; + line_number_w = 0; + breakpoint_gutter_width = 0; + fold_gutter_width = 0; + info_gutter_width = 0; + minimap_width = 0; + } } cache; Map<int, int> color_region_cache; @@ -240,6 +286,17 @@ private: uint32_t version; bool chain_forward; bool chain_backward; + TextOperation() { + type = TYPE_NONE; + from_line = 0; + from_column = 0; + to_line = 0; + to_column = 0; + prev_version = 0; + version = 0; + chain_forward = false; + chain_backward = false; + } }; String ime_text; diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp index e9b0bd8f38..9ffb69037a 100644 --- a/scene/gui/texture_button.cpp +++ b/scene/gui/texture_button.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/texture_button.h b/scene/gui/texture_button.h index d9224de686..e39b94abf0 100644 --- a/scene/gui/texture_button.h +++ b/scene/gui/texture_button.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/texture_progress.cpp b/scene/gui/texture_progress.cpp index 9b60a9d1c3..2d30ff7334 100644 --- a/scene/gui/texture_progress.cpp +++ b/scene/gui/texture_progress.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/texture_progress.h b/scene/gui/texture_progress.h index 008bf5b038..e4a40fd6a3 100644 --- a/scene/gui/texture_progress.h +++ b/scene/gui/texture_progress.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/texture_rect.cpp b/scene/gui/texture_rect.cpp index 473cee5ca1..514eff358e 100644 --- a/scene/gui/texture_rect.cpp +++ b/scene/gui/texture_rect.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -36,8 +36,9 @@ void TextureRect::_notification(int p_what) { if (p_what == NOTIFICATION_DRAW) { - if (texture.is_null()) + if (texture.is_null()) { return; + } Size2 size; Point2 offset; @@ -85,11 +86,11 @@ void TextureRect::_notification(int p_what) { size = get_size(); Size2 tex_size = texture->get_size(); - Size2 scaleSize(size.width / tex_size.width, size.height / tex_size.height); - float scale = scaleSize.width > scaleSize.height ? scaleSize.width : scaleSize.height; - Size2 scaledTexSize = tex_size * scale; + Size2 scale_size(size.width / tex_size.width, size.height / tex_size.height); + float scale = scale_size.width > scale_size.height ? scale_size.width : scale_size.height; + Size2 scaled_tex_size = tex_size * scale; - region.position = ((scaledTexSize - size) / scale).abs() / 2.0f; + region.position = ((scaled_tex_size - size) / scale).abs() / 2.0f; region.size = size / scale; } break; } @@ -107,11 +108,13 @@ void TextureRect::_notification(int p_what) { Size2 TextureRect::get_minimum_size() const { - if (!expand && !texture.is_null()) + if (!expand && !texture.is_null()) { return texture->get_size(); - else + } else { return Size2(); + } } + void TextureRect::_bind_methods() { ClassDB::bind_method(D_METHOD("set_texture", "texture"), &TextureRect::set_texture); @@ -152,22 +155,21 @@ void TextureRect::_texture_changed() { void TextureRect::set_texture(const Ref<Texture> &p_tex) { - if (p_tex == texture) + if (p_tex == texture) { return; + } - if (texture.is_valid()) + if (texture.is_valid()) { texture->disconnect(CoreStringNames::get_singleton()->changed, this, "_texture_changed"); + } texture = p_tex; - if (texture.is_valid()) + if (texture.is_valid()) { texture->connect(CoreStringNames::get_singleton()->changed, this, "_texture_changed"); + } update(); - /* - if (texture.is_valid()) - texture->set_flags(texture->get_flags()&(~Texture::FLAG_REPEAT)); //remove repeat from texture, it looks bad in sprites - */ minimum_size_changed(); } @@ -182,6 +184,7 @@ void TextureRect::set_expand(bool p_expand) { update(); minimum_size_changed(); } + bool TextureRect::has_expand() const { return expand; @@ -203,6 +206,7 @@ void TextureRect::set_flip_h(bool p_flip) { hflip = p_flip; update(); } + bool TextureRect::is_flipped_h() const { return hflip; @@ -213,6 +217,7 @@ void TextureRect::set_flip_v(bool p_flip) { vflip = p_flip; update(); } + bool TextureRect::is_flipped_v() const { return vflip; diff --git a/scene/gui/texture_rect.h b/scene/gui/texture_rect.h index d144020562..ef970fa051 100644 --- a/scene/gui/texture_rect.h +++ b/scene/gui/texture_rect.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/tool_button.cpp b/scene/gui/tool_button.cpp index a81cc34efa..c9f87f0015 100644 --- a/scene/gui/tool_button.cpp +++ b/scene/gui/tool_button.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/tool_button.h b/scene/gui/tool_button.h index 8f729cd4df..9848b21381 100644 --- a/scene/gui/tool_button.h +++ b/scene/gui/tool_button.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index d479a1636a..790e1d5f4f 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -1121,7 +1121,7 @@ void Tree::draw_item_rect(const TreeItem::Cell &p_cell, const Rect2i &p_rect, co } rect.position.y += Math::floor((rect.size.y - font->get_height()) / 2.0) + font->get_ascent(); - font->draw(ci, rect.position, text, p_color, rect.size.x); + font->draw(ci, rect.position, text, p_color, MAX(0, rect.size.width)); } int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 &p_draw_size, TreeItem *p_item) { @@ -2162,9 +2162,8 @@ void Tree::_go_right() { if (selected_item->get_children() != NULL && selected_item->is_collapsed()) { selected_item->set_collapsed(false); } else if (selected_item->get_next_visible()) { - selected_item->select(0); + selected_col = 0; _go_down(); - return; } } else { if (select_mode == SELECT_MULTI) { @@ -2746,9 +2745,13 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { Ref<InputEventPanGesture> pan_gesture = p_event; if (pan_gesture.is_valid()) { - double prev_value = v_scroll->get_value(); + double prev_v = v_scroll->get_value(); v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * pan_gesture->get_delta().y / 8); - if (v_scroll->get_value() != prev_value) { + + double prev_h = h_scroll->get_value(); + h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * pan_gesture->get_delta().x / 8); + + if (v_scroll->get_value() != prev_v || h_scroll->get_value() != prev_h) { accept_event(); } } @@ -3427,7 +3430,10 @@ int Tree::get_item_offset(TreeItem *p_item) const { if (it == p_item) return ofs; - ofs += compute_item_height(it) + cache.vseparation; + ofs += compute_item_height(it); + if (it != root || !hide_root) { + ofs += cache.vseparation; + } if (it->children && !it->collapsed) { @@ -3453,25 +3459,48 @@ int Tree::get_item_offset(TreeItem *p_item) const { } void Tree::ensure_cursor_is_visible() { - - if (!is_inside_tree()) + if (!is_inside_tree()) { return; + } + if (!selected_item || (selected_col == -1)) { + return; // Nothing under cursor. + } - TreeItem *selected = get_selected(); - if (!selected) - return; - int ofs = get_item_offset(selected); - if (ofs == -1) - return; - int h = compute_item_height(selected) + cache.vseparation; - int screenh = get_size().height - h_scroll->get_combined_minimum_size().height; + const Size2 area_size = get_size() - cache.bg->get_minimum_size(); + + int y_offset = get_item_offset(selected_item); + if (y_offset != -1) { + const int tbh = _get_title_button_height(); + y_offset -= tbh; - if (h > screenh) { //screen size is too small, maybe it was not resized yet. - v_scroll->set_value(ofs); - } else if (ofs + h > v_scroll->get_value() + screenh) { - v_scroll->call_deferred("set_value", ofs - screenh + h); - } else if (ofs < v_scroll->get_value()) { - v_scroll->set_value(ofs); + const int cell_h = compute_item_height(selected_item) + cache.vseparation; + const int screen_h = area_size.height - h_scroll->get_combined_minimum_size().height - tbh; + + if (cell_h > screen_h) { // Screen size is too small, maybe it was not resized yet. + v_scroll->set_value(y_offset); + } else if (y_offset + cell_h > v_scroll->get_value() + screen_h) { + v_scroll->call_deferred("set_value", y_offset - screen_h + cell_h); + } else if (y_offset < v_scroll->get_value()) { + v_scroll->set_value(y_offset); + } + } + + if (select_mode != SELECT_ROW) { // Cursor always at col 0 in this mode. + int x_offset = 0; + for (int i = 0; i < selected_col; i++) { + x_offset += get_column_width(i); + } + + const int cell_w = get_column_width(selected_col); + const int screen_w = area_size.width - v_scroll->get_combined_minimum_size().width; + + if (cell_w > screen_w) { + h_scroll->set_value(x_offset); + } else if (x_offset + cell_w > h_scroll->get_value() + screen_w) { + h_scroll->call_deferred("set_value", x_offset - screen_w + cell_w); + } else if (x_offset < h_scroll->get_value()) { + h_scroll->set_value(x_offset); + } } } @@ -3601,6 +3630,17 @@ TreeItem *Tree::search_item_text(const String &p_find, int *r_col, bool p_select return _search_item_text(from->get_next_visible(true), p_find, r_col, p_selectable); } +TreeItem *Tree::get_item_with_text(const String &p_find) const { + for (TreeItem *current = root; current; current = current->get_next_visible()) { + for (int i = 0; i < columns.size(); i++) { + if (current->get_text(i) == p_find) { + return current; + } + } + } + return NULL; +} + void Tree::_do_incr_search(const String &p_add) { uint64_t time = OS::get_singleton()->get_ticks_usec() / 1000; // convert to msec diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 361830173b..f3c88eb5ac 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -159,7 +159,7 @@ protected: //bind helpers Dictionary _get_range_config(int p_column) { Dictionary d; - double min, max, step; + double min = 0.0, max = 0.0, step = 0.0; get_range_config(p_column, min, max, step); d["min"] = min; d["max"] = max; @@ -577,7 +577,10 @@ public: Rect2 get_item_rect(TreeItem *p_item, int p_column = -1) const; bool edit_selected(); + // First item that starts with the text, from the current focused item down and wraps around. TreeItem *search_item_text(const String &p_find, int *r_col = NULL, bool p_selectable = false); + // First item that matches the whole text, from the first item down. + TreeItem *get_item_with_text(const String &p_find) const; Point2 get_scroll() const; void scroll_to_item(TreeItem *p_item); diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp index fd2d4a1a11..0a693d4023 100644 --- a/scene/gui/video_player.cpp +++ b/scene/gui/video_player.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -249,6 +249,10 @@ void VideoPlayer::set_stream(const Ref<VideoStream> &p_stream) { } update(); + + if (!expand) { + minimum_size_changed(); + } }; Ref<VideoStream> VideoPlayer::get_stream() const { diff --git a/scene/gui/video_player.h b/scene/gui/video_player.h index 7d2821427e..e740e3e4ed 100644 --- a/scene/gui/video_player.h +++ b/scene/gui/video_player.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/viewport_container.cpp b/scene/gui/viewport_container.cpp index 35696a0459..4565b4b538 100644 --- a/scene/gui/viewport_container.cpp +++ b/scene/gui/viewport_container.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/viewport_container.h b/scene/gui/viewport_container.h index b4ecc583ba..8597444426 100644 --- a/scene/gui/viewport_container.h +++ b/scene/gui/viewport_container.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp index 8cab1b1280..4ae018a79a 100644 --- a/scene/main/canvas_layer.cpp +++ b/scene/main/canvas_layer.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/main/canvas_layer.h b/scene/main/canvas_layer.h index fa2558556c..91ddbca3b9 100644 --- a/scene/main/canvas_layer.h +++ b/scene/main/canvas_layer.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index 6c922adbd2..3c89069816 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -457,6 +457,18 @@ String HTTPRequest::get_download_file() const { return download_to_file; } + +void HTTPRequest::set_download_chunk_size(int p_chunk_size) { + + ERR_FAIL_COND(get_http_client_status() != HTTPClient::STATUS_DISCONNECTED); + + client->set_read_chunk_size(p_chunk_size); +} + +int HTTPRequest::get_download_chunk_size() const { + return client->get_read_chunk_size(); +} + HTTPClient::Status HTTPRequest::get_http_client_status() const { return client->get_status(); } @@ -524,9 +536,13 @@ void HTTPRequest::_bind_methods() { ClassDB::bind_method(D_METHOD("set_timeout", "timeout"), &HTTPRequest::set_timeout); ClassDB::bind_method(D_METHOD("get_timeout"), &HTTPRequest::get_timeout); + ClassDB::bind_method(D_METHOD("set_download_chunk_size"), &HTTPRequest::set_download_chunk_size); + ClassDB::bind_method(D_METHOD("get_download_chunk_size"), &HTTPRequest::get_download_chunk_size); + ClassDB::bind_method(D_METHOD("_timeout"), &HTTPRequest::_timeout); ADD_PROPERTY(PropertyInfo(Variant::STRING, "download_file", PROPERTY_HINT_FILE), "set_download_file", "get_download_file"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "download_chunk_size", PROPERTY_HINT_RANGE, "256,16777216"), "set_download_chunk_size", "get_download_chunk_size"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_threads"), "set_use_threads", "is_using_threads"); ADD_PROPERTY(PropertyInfo(Variant::INT, "body_size_limit", PROPERTY_HINT_RANGE, "-1,2000000000"), "set_body_size_limit", "get_body_size_limit"); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_redirects", PROPERTY_HINT_RANGE, "-1,64"), "set_max_redirects", "get_max_redirects"); diff --git a/scene/main/http_request.h b/scene/main/http_request.h index f1f91235a6..94b323ae8a 100644 --- a/scene/main/http_request.h +++ b/scene/main/http_request.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -126,6 +126,9 @@ public: void set_download_file(const String &p_file); String get_download_file() const; + void set_download_chunk_size(int p_chunk_size); + int get_download_chunk_size() const; + void set_body_size_limit(int p_bytes); int get_body_size_limit() const; diff --git a/scene/main/instance_placeholder.cpp b/scene/main/instance_placeholder.cpp index 99ecc8bc37..0128d1a218 100644 --- a/scene/main/instance_placeholder.cpp +++ b/scene/main/instance_placeholder.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/main/instance_placeholder.h b/scene/main/instance_placeholder.h index 3d0e879b2b..d570b8c247 100644 --- a/scene/main/instance_placeholder.h +++ b/scene/main/instance_placeholder.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 2a2a6bb41d..761fe3f90f 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -835,19 +835,26 @@ bool Node::is_processing_internal() const { void Node::set_process_priority(int p_priority) { data.process_priority = p_priority; - ERR_FAIL_COND(!data.tree); + // Make sure we are in SceneTree. + if (data.tree == NULL) { + return; + } - if (is_processing()) + if (is_processing()) { data.tree->make_group_changed("idle_process"); + } - if (is_processing_internal()) + if (is_processing_internal()) { data.tree->make_group_changed("idle_process_internal"); + } - if (is_physics_processing()) + if (is_physics_processing()) { data.tree->make_group_changed("physics_process"); + } - if (is_physics_processing_internal()) + if (is_physics_processing_internal()) { data.tree->make_group_changed("physics_process_internal"); + } } int Node::get_process_priority() const { @@ -1185,7 +1192,7 @@ void Node::add_child_below_node(Node *p_node, Node *p_child, bool p_legible_uniq if (is_a_parent_of(p_node)) { move_child(p_child, p_node->get_position_in_parent() + 1); } else { - WARN_PRINTS("Cannot move under node " + p_node->get_name() + " as " + p_child->get_name() + " does not share a parent."); + WARN_PRINT("Cannot move under node " + p_node->get_name() + " as " + p_child->get_name() + " does not share a parent."); } } @@ -2673,7 +2680,8 @@ void Node::clear_internal_tree_resource_paths() { String Node::get_configuration_warning() const { - if (get_script_instance() && get_script_instance()->has_method("_get_configuration_warning")) { + if (get_script_instance() && get_script_instance()->get_script().is_valid() && + get_script_instance()->get_script()->is_tool() && get_script_instance()->has_method("_get_configuration_warning")) { return get_script_instance()->call("_get_configuration_warning"); } return String(); diff --git a/scene/main/node.h b/scene/main/node.h index 6d0ff7e5cf..6f5544d654 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/main/resource_preloader.cpp b/scene/main/resource_preloader.cpp index cb1168b73e..5582ed59b0 100644 --- a/scene/main/resource_preloader.cpp +++ b/scene/main/resource_preloader.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/main/resource_preloader.h b/scene/main/resource_preloader.h index 3e3be4ac82..d03c784883 100644 --- a/scene/main/resource_preloader.h +++ b/scene/main/resource_preloader.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 3a6fff45c5..15d21859ea 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -46,6 +46,7 @@ #include "scene/resources/mesh.h" #include "scene/resources/packed_scene.h" #include "scene/scene_string_names.h" +#include "servers/navigation_server.h" #include "servers/physics_2d_server.h" #include "servers/physics_server.h" #include "viewport.h" @@ -423,6 +424,7 @@ void SceneTree::input_event(const Ref<InputEvent> &p_event) { input_handled = false; + // Don't make const ref unless you can find and fix what caused GH-34691. Ref<InputEvent> ev = p_event; MainLoop::input_event(ev); @@ -458,10 +460,7 @@ void SceneTree::input_event(const Ref<InputEvent> &p_event) { } void SceneTree::init() { - - //_quit=false; initialized = true; - root->_set_tree(this); MainLoop::init(); } @@ -631,7 +630,13 @@ void SceneTree::finish() { timers.clear(); } -void SceneTree::quit() { +void SceneTree::quit(int p_exit_code) { + + if (p_exit_code >= 0) { + // Override the exit code if a positive argument is given (the default is `-1`). + // This is a shorthand for calling `set_exit_code()` on the OS singleton then quitting. + OS::get_singleton()->set_exit_code(p_exit_code); + } _quit = true; } @@ -892,6 +897,7 @@ void SceneTree::set_pause(bool p_enabled) { if (p_enabled == pause) return; pause = p_enabled; + NavigationServer::get_singleton()->set_active(!p_enabled); PhysicsServer::get_singleton()->set_active(!p_enabled); Physics2DServer::get_singleton()->set_active(!p_enabled); if (get_root()) @@ -1278,6 +1284,14 @@ void SceneTree::_change_scene(Node *p_to) { current_scene = NULL; } + // If we're quitting, abort. + if (unlikely(_quit)) { + if (p_to) { // Prevent memory leak. + memdelete(p_to); + } + return; + } + if (p_to) { current_scene = p_to; root->add_child(p_to); @@ -1285,15 +1299,14 @@ void SceneTree::_change_scene(Node *p_to) { } Error SceneTree::change_scene(const String &p_path) { - Ref<PackedScene> new_scene = ResourceLoader::load(p_path); if (new_scene.is_null()) return ERR_CANT_OPEN; return change_scene_to(new_scene); } -Error SceneTree::change_scene_to(const Ref<PackedScene> &p_scene) { +Error SceneTree::change_scene_to(const Ref<PackedScene> &p_scene) { Node *new_scene = NULL; if (p_scene.is_valid()) { new_scene = p_scene->instance(); @@ -1303,8 +1316,8 @@ Error SceneTree::change_scene_to(const Ref<PackedScene> &p_scene) { call_deferred("_change_scene", new_scene); return OK; } -Error SceneTree::reload_current_scene() { +Error SceneTree::reload_current_scene() { ERR_FAIL_COND_V(!current_scene, ERR_UNCONFIGURED); String fname = current_scene->get_filename(); return change_scene(fname); @@ -1315,6 +1328,7 @@ void SceneTree::add_current_scene(Node *p_current) { current_scene = p_current; root->add_child(p_current); } + #ifdef DEBUG_ENABLED static void _fill_array(Node *p_node, Array &array, int p_level) { @@ -1812,8 +1826,6 @@ bool SceneTree::is_refusing_new_network_connections() const { void SceneTree::_bind_methods() { - //ClassDB::bind_method(D_METHOD("call_group","call_flags","group","method","arg1","arg2"),&SceneMainLoop::_call_group,DEFVAL(Variant()),DEFVAL(Variant())); - ClassDB::bind_method(D_METHOD("get_root"), &SceneTree::get_root); ClassDB::bind_method(D_METHOD("has_group", "name"), &SceneTree::has_group); @@ -1837,7 +1849,7 @@ void SceneTree::_bind_methods() { ClassDB::bind_method(D_METHOD("get_node_count"), &SceneTree::get_node_count); ClassDB::bind_method(D_METHOD("get_frame"), &SceneTree::get_frame); - ClassDB::bind_method(D_METHOD("quit"), &SceneTree::quit); + ClassDB::bind_method(D_METHOD("quit", "exit_code"), &SceneTree::quit, DEFVAL(-1)); ClassDB::bind_method(D_METHOD("set_screen_stretch", "mode", "aspect", "minsize", "shrink"), &SceneTree::set_screen_stretch, DEFVAL(1)); @@ -2102,7 +2114,7 @@ SceneTree::SceneTree() { ProjectSettings::get_singleton()->set("rendering/environment/default_environment", ""); } else { //file was erased, notify user. - ERR_PRINTS(RTR("Default Environment as specified in Project Settings (Rendering -> Environment -> Default Environment) could not be loaded.")); + ERR_PRINT(RTR("Default Environment as specified in Project Settings (Rendering -> Environment -> Default Environment) could not be loaded.")); } } } diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index 2cf6a117e7..55304fb12d 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -303,7 +303,7 @@ public: void set_auto_accept_quit(bool p_enable); void set_quit_on_go_back(bool p_enable); - void quit(); + void quit(int p_exit_code = -1); void set_input_as_handled(); bool is_input_handled(); diff --git a/scene/main/timer.cpp b/scene/main/timer.cpp index 14cc705edb..cb213be731 100755 --- a/scene/main/timer.cpp +++ b/scene/main/timer.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -108,7 +108,7 @@ bool Timer::has_autostart() const { void Timer::start(float p_time) { - ERR_FAIL_COND_MSG(!is_inside_tree(), "Timer was not added to the SceneTree!"); + ERR_FAIL_COND_MSG(!is_inside_tree(), "Timer was not added to the SceneTree. Either add it or set autostart to true."); if (p_time > 0) { set_wait_time(p_time); @@ -206,7 +206,7 @@ void Timer::_bind_methods() { ADD_SIGNAL(MethodInfo("timeout")); ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_timer_process_mode", "get_timer_process_mode"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "wait_time", PROPERTY_HINT_EXP_RANGE, "0.01,4096,0.01"), "set_wait_time", "get_wait_time"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "wait_time", PROPERTY_HINT_EXP_RANGE, "0.001,4096,0.001,or_greater"), "set_wait_time", "get_wait_time"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "is_one_shot"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autostart"), "set_autostart", "has_autostart"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "paused", PROPERTY_HINT_NONE, "", 0), "set_paused", "is_paused"); diff --git a/scene/main/timer.h b/scene/main/timer.h index c492c6b61c..044566738e 100755 --- a/scene/main/timer.h +++ b/scene/main/timer.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 563fcb9961..72ab817e98 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,6 +30,7 @@ #include "viewport.h" +#include "core/core_string_names.h" #include "core/os/input.h" #include "core/os/os.h" #include "core/project_settings.h" @@ -251,6 +252,27 @@ void Viewport::_collision_object_input_event(CollisionObject *p_object, Camera * physics_last_id = id; } +void Viewport::_own_world_changed() { + ERR_FAIL_COND(world.is_null()); + ERR_FAIL_COND(own_world.is_null()); + + if (is_inside_tree()) { + _propagate_exit_world(this); + } + + own_world = world->duplicate(); + + if (is_inside_tree()) { + _propagate_enter_world(this); + } + + if (is_inside_tree()) { + VisualServer::get_singleton()->viewport_set_scenario(viewport, find_world()->get_scenario()); + } + + _update_listener(); +} + void Viewport::_notification(int p_what) { switch (p_what) { @@ -1105,8 +1127,21 @@ void Viewport::set_world(const Ref<World> &p_world) { if (is_inside_tree()) _propagate_exit_world(this); + if (own_world.is_valid() && world.is_valid()) { + world->disconnect(CoreStringNames::get_singleton()->changed, this, "_own_world_changed"); + } + world = p_world; + if (own_world.is_valid()) { + if (world.is_valid()) { + own_world = world->duplicate(); + world->connect(CoreStringNames::get_singleton()->changed, this, "_own_world_changed"); + } else { + own_world = Ref<World>(memnew(World)); + } + } + if (is_inside_tree()) _propagate_enter_world(this); @@ -1810,7 +1845,7 @@ bool Viewport::_gui_drop(Control *p_at_control, Point2 p_at_pos, bool p_just_che void Viewport::_gui_input_event(Ref<InputEvent> p_event) { - ERR_FAIL_COND(p_event.is_null()) + ERR_FAIL_COND(p_event.is_null()); //? /* @@ -2407,12 +2442,12 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { Input *input = Input::get_singleton(); - if (!mods && p_event->is_action_pressed("ui_focus_next") && input->is_action_just_pressed("ui_focus_next")) { + if (p_event->is_action_pressed("ui_focus_next") && input->is_action_just_pressed("ui_focus_next")) { next = from->find_next_valid_focus(); } - if (!mods && p_event->is_action_pressed("ui_focus_prev") && input->is_action_just_pressed("ui_focus_prev")) { + if (p_event->is_action_pressed("ui_focus_prev") && input->is_action_just_pressed("ui_focus_prev")) { next = from->find_prev_valid_focus(); } @@ -2634,6 +2669,7 @@ void Viewport::_gui_control_grab_focus(Control *p_control) { return; get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, "_viewports", "_gui_remove_focus"); gui.key_focus = p_control; + emit_signal("gui_focus_changed", p_control); p_control->notification(Control::NOTIFICATION_FOCUS_ENTER); p_control->update(); } @@ -2825,10 +2861,19 @@ void Viewport::set_use_own_world(bool p_world) { if (is_inside_tree()) _propagate_exit_world(this); - if (!p_world) + if (!p_world) { own_world = Ref<World>(); - else - own_world = Ref<World>(memnew(World)); + if (world.is_valid()) { + world->disconnect(CoreStringNames::get_singleton()->changed, this, "_own_world_changed"); + } + } else { + if (world.is_valid()) { + own_world = world->duplicate(); + world->connect(CoreStringNames::get_singleton()->changed, this, "_own_world_changed"); + } else { + own_world = Ref<World>(memnew(World)); + } + } if (is_inside_tree()) _propagate_enter_world(this); @@ -3177,6 +3222,8 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("_subwindow_visibility_changed"), &Viewport::_subwindow_visibility_changed); + ClassDB::bind_method(D_METHOD("_own_world_changed"), &Viewport::_own_world_changed); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "arvr"), "set_use_arvr", "use_arvr"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size"); @@ -3187,7 +3234,7 @@ void Viewport::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "transparent_bg"), "set_transparent_background", "has_transparent_background"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "handle_input_locally"), "set_handle_input_locally", "is_handling_input_locally"); ADD_GROUP("Rendering", ""); - ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x,External 2x,External 4x"), "set_msaa", "get_msaa"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x,AndroidVR 2x,AndroidVR 4x"), "set_msaa", "get_msaa"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hdr"), "set_hdr", "get_hdr"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_3d"), "set_disable_3d", "is_3d_disabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_3d_linear"), "set_keep_3d_linear", "get_keep_3d_linear"); @@ -3216,6 +3263,7 @@ void Viewport::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "global_canvas_transform", PROPERTY_HINT_NONE, "", 0), "set_global_canvas_transform", "get_global_canvas_transform"); ADD_SIGNAL(MethodInfo("size_changed")); + ADD_SIGNAL(MethodInfo("gui_focus_changed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Control"))); BIND_ENUM_CONSTANT(UPDATE_DISABLED); BIND_ENUM_CONSTANT(UPDATE_ONCE); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 3c3b436ca1..79b606cda3 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -406,6 +406,8 @@ private: void _update_canvas_items(Node *p_node); + void _own_world_changed(); + protected: void _notification(int p_what); static void _bind_methods(); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 314fc721fc..433c015a33 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -50,6 +50,8 @@ #include "scene/2d/mesh_instance_2d.h" #include "scene/2d/multimesh_instance_2d.h" #include "scene/2d/navigation_2d.h" +#include "scene/2d/navigation_agent_2d.h" +#include "scene/2d/navigation_obstacle_2d.h" #include "scene/2d/parallax_background.h" #include "scene/2d/parallax_layer.h" #include "scene/2d/particles_2d.h" @@ -71,7 +73,6 @@ #include "scene/animation/animation_node_state_machine.h" #include "scene/animation/animation_player.h" #include "scene/animation/animation_tree.h" -#include "scene/animation/animation_tree_player.h" #include "scene/animation/root_motion_view.h" #include "scene/animation/tween.h" #include "scene/audio/audio_stream_player.h" @@ -145,6 +146,7 @@ #include "scene/resources/material.h" #include "scene/resources/mesh.h" #include "scene/resources/mesh_data_tool.h" +#include "scene/resources/navigation_mesh.h" #include "scene/resources/packed_scene.h" #include "scene/resources/particles_material.h" #include "scene/resources/physics_material.h" @@ -168,9 +170,6 @@ #include "scene/resources/world_2d.h" #include "scene/scene_string_names.h" -#include "scene/3d/spatial.h" -#include "scene/3d/world_environment.h" - #ifndef _3D_DISABLED #include "scene/3d/area.h" #include "scene/3d/arvr_nodes.h" @@ -189,24 +188,26 @@ #include "scene/3d/mesh_instance.h" #include "scene/3d/multimesh_instance.h" #include "scene/3d/navigation.h" -#include "scene/3d/navigation_mesh.h" +#include "scene/3d/navigation_agent.h" +#include "scene/3d/navigation_mesh_instance.h" +#include "scene/3d/navigation_obstacle.h" #include "scene/3d/particles.h" #include "scene/3d/path.h" #include "scene/3d/physics_body.h" #include "scene/3d/physics_joint.h" -#include "scene/3d/portal.h" #include "scene/3d/position_3d.h" #include "scene/3d/proximity_group.h" #include "scene/3d/ray_cast.h" #include "scene/3d/reflection_probe.h" #include "scene/3d/remote_transform.h" -#include "scene/3d/room_instance.h" #include "scene/3d/skeleton.h" #include "scene/3d/soft_body.h" +#include "scene/3d/spatial.h" #include "scene/3d/spring_arm.h" #include "scene/3d/sprite_3d.h" #include "scene/3d/vehicle_body.h" #include "scene/3d/visibility_notifier.h" +#include "scene/3d/world_environment.h" #include "scene/animation/skeleton_ik.h" #include "scene/resources/environment.h" #include "scene/resources/mesh_library.h" @@ -372,6 +373,27 @@ void register_scene_types() { ClassDB::register_class<AnimationPlayer>(); ClassDB::register_class<Tween>(); + ClassDB::register_class<AnimationTree>(); + ClassDB::register_class<AnimationNode>(); + ClassDB::register_class<AnimationRootNode>(); + ClassDB::register_class<AnimationNodeBlendTree>(); + ClassDB::register_class<AnimationNodeBlendSpace1D>(); + ClassDB::register_class<AnimationNodeBlendSpace2D>(); + ClassDB::register_class<AnimationNodeStateMachine>(); + ClassDB::register_class<AnimationNodeStateMachinePlayback>(); + + ClassDB::register_class<AnimationNodeStateMachineTransition>(); + ClassDB::register_class<AnimationNodeOutput>(); + ClassDB::register_class<AnimationNodeOneShot>(); + ClassDB::register_class<AnimationNodeAnimation>(); + ClassDB::register_class<AnimationNodeAdd2>(); + ClassDB::register_class<AnimationNodeAdd3>(); + ClassDB::register_class<AnimationNodeBlend2>(); + ClassDB::register_class<AnimationNodeBlend3>(); + ClassDB::register_class<AnimationNodeTimeScale>(); + ClassDB::register_class<AnimationNodeTimeSeek>(); + ClassDB::register_class<AnimationNodeTransition>(); + OS::get_singleton()->yield(); //may take time to init #ifndef _3D_DISABLED @@ -399,38 +421,13 @@ void register_scene_types() { ClassDB::register_class<GIProbeData>(); ClassDB::register_class<BakedLightmap>(); ClassDB::register_class<BakedLightmapData>(); - ClassDB::register_class<AnimationTreePlayer>(); ClassDB::register_class<Particles>(); ClassDB::register_class<CPUParticles>(); ClassDB::register_class<Position3D>(); - ClassDB::register_class<NavigationMeshInstance>(); - ClassDB::register_class<NavigationMesh>(); - ClassDB::register_class<Navigation>(); ClassDB::register_class<RootMotionView>(); ClassDB::set_class_enabled("RootMotionView", false); //disabled by default, enabled by editor - ClassDB::register_class<AnimationTree>(); - ClassDB::register_class<AnimationNode>(); - ClassDB::register_class<AnimationRootNode>(); - ClassDB::register_class<AnimationNodeBlendTree>(); - ClassDB::register_class<AnimationNodeBlendSpace1D>(); - ClassDB::register_class<AnimationNodeBlendSpace2D>(); - ClassDB::register_class<AnimationNodeStateMachine>(); - ClassDB::register_class<AnimationNodeStateMachinePlayback>(); - - ClassDB::register_class<AnimationNodeStateMachineTransition>(); - ClassDB::register_class<AnimationNodeOutput>(); - ClassDB::register_class<AnimationNodeOneShot>(); - ClassDB::register_class<AnimationNodeAnimation>(); - ClassDB::register_class<AnimationNodeAdd2>(); - ClassDB::register_class<AnimationNodeAdd3>(); - ClassDB::register_class<AnimationNodeBlend2>(); - ClassDB::register_class<AnimationNodeBlend3>(); - ClassDB::register_class<AnimationNodeTimeScale>(); - ClassDB::register_class<AnimationNodeTimeSeek>(); - ClassDB::register_class<AnimationNodeTransition>(); - OS::get_singleton()->yield(); //may take time to init ClassDB::register_virtual_class<CollisionObject>(); @@ -471,9 +468,15 @@ void register_scene_types() { ClassDB::register_class<ConeTwistJoint>(); ClassDB::register_class<Generic6DOFJoint>(); + ClassDB::register_class<Navigation>(); + ClassDB::register_class<NavigationMeshInstance>(); + ClassDB::register_class<NavigationAgent>(); + ClassDB::register_class<NavigationObstacle>(); + OS::get_singleton()->yield(); //may take time to init #endif + ClassDB::register_class<NavigationMesh>(); AcceptDialog::set_swap_ok_cancel(GLOBAL_DEF("gui/common/swap_ok_cancel", bool(OS::get_singleton()->get_swap_ok_cancel()))); @@ -715,6 +718,8 @@ void register_scene_types() { ClassDB::register_class<Navigation2D>(); ClassDB::register_class<NavigationPolygon>(); ClassDB::register_class<NavigationPolygonInstance>(); + ClassDB::register_class<NavigationAgent2D>(); + ClassDB::register_class<NavigationObstacle2D>(); OS::get_singleton()->yield(); //may take time to init @@ -728,7 +733,7 @@ void register_scene_types() { ClassDB::add_compatibility_class("ImageSkyBox", "PanoramaSky"); ClassDB::add_compatibility_class("FixedSpatialMaterial", "SpatialMaterial"); ClassDB::add_compatibility_class("Mesh", "ArrayMesh"); - + ClassDB::add_compatibility_class("AnimationTreePlayer", "AnimationTree"); #endif OS::get_singleton()->yield(); //may take time to init @@ -751,7 +756,7 @@ void register_scene_types() { if (font_path != String()) { font = ResourceLoader::load(font_path); if (!font.is_valid()) { - ERR_PRINTS("Error loading custom font '" + font_path + "'"); + ERR_PRINT("Error loading custom font '" + font_path + "'"); } } @@ -766,7 +771,7 @@ void register_scene_types() { Theme::set_default_font(font); } } else { - ERR_PRINTS("Error loading custom theme '" + theme_path + "'"); + ERR_PRINT("Error loading custom theme '" + theme_path + "'"); } } } diff --git a/scene/register_scene_types.h b/scene/register_scene_types.h index b551ad2ac4..603321991e 100644 --- a/scene/register_scene_types.h +++ b/scene/register_scene_types.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index f4ac277d00..91d1e32053 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/animation.h b/scene/resources/animation.h index d59dfab2c8..6ac0ea04d9 100644 --- a/scene/resources/animation.h +++ b/scene/resources/animation.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_sample.cpp index 5b61654c5d..a412d8a5e2 100644 --- a/scene/resources/audio_stream_sample.cpp +++ b/scene/resources/audio_stream_sample.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,6 +29,7 @@ /*************************************************************************/ #include "audio_stream_sample.h" + #include "core/io/marshalls.h" #include "core/os/file_access.h" @@ -95,8 +96,8 @@ void AudioStreamPlaybackSample::do_resample(const Depth *p_src, AudioFrame *p_ds // this function will be compiled branchless by any decent compiler int32_t final, final_r, next, next_r; - while (amount--) { - + while (amount) { + amount--; int64_t pos = offset >> MIX_FRAC_BITS; if (is_stereo && !is_ima_adpcm) pos <<= 1; @@ -444,6 +445,7 @@ int AudioStreamSample::get_loop_end() const { void AudioStreamSample::set_mix_rate(int p_hz) { + ERR_FAIL_COND(p_hz == 0); mix_rate = p_hz; } int AudioStreamSample::get_mix_rate() const { @@ -517,7 +519,7 @@ PoolVector<uint8_t> AudioStreamSample::get_data() const { Error AudioStreamSample::save_to_wav(const String &p_path) { if (format == AudioStreamSample::FORMAT_IMA_ADPCM) { - WARN_PRINTS("Saving IMA_ADPC samples are not supported yet"); + WARN_PRINT("Saving IMA_ADPC samples are not supported yet"); return ERR_UNAVAILABLE; } @@ -655,8 +657,8 @@ AudioStreamSample::AudioStreamSample() { data = NULL; data_bytes = 0; } -AudioStreamSample::~AudioStreamSample() { +AudioStreamSample::~AudioStreamSample() { if (data) { AudioServer::get_singleton()->audio_data_free(data); data = NULL; diff --git a/scene/resources/audio_stream_sample.h b/scene/resources/audio_stream_sample.h index bb25b60835..adcac14ea8 100644 --- a/scene/resources/audio_stream_sample.h +++ b/scene/resources/audio_stream_sample.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef AUDIOSTREAMSAMPLE_H -#define AUDIOSTREAMSAMPLE_H +#ifndef AUDIO_STREAM_SAMPLE_H +#define AUDIO_STREAM_SAMPLE_H #include "servers/audio/audio_stream.h" @@ -153,4 +153,4 @@ public: VARIANT_ENUM_CAST(AudioStreamSample::Format) VARIANT_ENUM_CAST(AudioStreamSample::LoopMode) -#endif // AUDIOSTREAMSample_H +#endif // AUDIO_STREAM_SAMPLE_H diff --git a/scene/resources/bit_map.cpp b/scene/resources/bit_map.cpp index e6139dd707..06323a8d31 100644 --- a/scene/resources/bit_map.cpp +++ b/scene/resources/bit_map.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/bit_map.h b/scene/resources/bit_map.h index b062dd7376..ed332dffa4 100644 --- a/scene/resources/bit_map.h +++ b/scene/resources/bit_map.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/box_shape.cpp b/scene/resources/box_shape.cpp index c6fe14e55e..e1f485bae6 100644 --- a/scene/resources/box_shape.cpp +++ b/scene/resources/box_shape.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -48,6 +48,10 @@ Vector<Vector3> BoxShape::get_debug_mesh_lines() { return lines; } +real_t BoxShape::get_enclosing_radius() const { + return extents.length(); +} + void BoxShape::_update_shape() { PhysicsServer::get_singleton()->shape_set_data(get_shape(), extents); diff --git a/scene/resources/box_shape.h b/scene/resources/box_shape.h index 0bce929aee..fb164cc300 100644 --- a/scene/resources/box_shape.h +++ b/scene/resources/box_shape.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -48,6 +48,7 @@ public: Vector3 get_extents() const; virtual Vector<Vector3> get_debug_mesh_lines(); + virtual real_t get_enclosing_radius() const; BoxShape(); }; diff --git a/scene/resources/canvas.cpp b/scene/resources/canvas.cpp index 0fc8b22046..1dbd02ea28 100644 --- a/scene/resources/canvas.cpp +++ b/scene/resources/canvas.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/canvas.h b/scene/resources/canvas.h index 4324b6227c..621911fe0a 100644 --- a/scene/resources/canvas.h +++ b/scene/resources/canvas.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/capsule_shape.cpp b/scene/resources/capsule_shape.cpp index 1ec3bd7158..933129936a 100644 --- a/scene/resources/capsule_shape.cpp +++ b/scene/resources/capsule_shape.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -69,6 +69,10 @@ Vector<Vector3> CapsuleShape::get_debug_mesh_lines() { return points; } +real_t CapsuleShape::get_enclosing_radius() const { + return radius + height * 0.5; +} + void CapsuleShape::_update_shape() { Dictionary d; diff --git a/scene/resources/capsule_shape.h b/scene/resources/capsule_shape.h index befbc1dcd5..f097e51175 100644 --- a/scene/resources/capsule_shape.h +++ b/scene/resources/capsule_shape.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -51,6 +51,7 @@ public: float get_height() const; virtual Vector<Vector3> get_debug_mesh_lines(); + virtual real_t get_enclosing_radius() const; CapsuleShape(); }; diff --git a/scene/resources/capsule_shape_2d.cpp b/scene/resources/capsule_shape_2d.cpp index fde05bfb7f..5658395cee 100644 --- a/scene/resources/capsule_shape_2d.cpp +++ b/scene/resources/capsule_shape_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -97,6 +97,10 @@ Rect2 CapsuleShape2D::get_rect() const { return rect; } +real_t CapsuleShape2D::get_enclosing_radius() const { + return radius + height * 0.5; +} + void CapsuleShape2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CapsuleShape2D::set_radius); diff --git a/scene/resources/capsule_shape_2d.h b/scene/resources/capsule_shape_2d.h index 3bedf7618d..fe401a610c 100644 --- a/scene/resources/capsule_shape_2d.h +++ b/scene/resources/capsule_shape_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -56,6 +56,7 @@ public: virtual void draw(const RID &p_to_rid, const Color &p_color); virtual Rect2 get_rect() const; + virtual real_t get_enclosing_radius() const; CapsuleShape2D(); }; diff --git a/scene/resources/circle_shape_2d.cpp b/scene/resources/circle_shape_2d.cpp index 76c1440861..10f8ab8a8a 100644 --- a/scene/resources/circle_shape_2d.cpp +++ b/scene/resources/circle_shape_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -70,6 +70,10 @@ Rect2 CircleShape2D::get_rect() const { return rect; } +real_t CircleShape2D::get_enclosing_radius() const { + return radius; +} + void CircleShape2D::draw(const RID &p_to_rid, const Color &p_color) { Vector<Vector2> points; diff --git a/scene/resources/circle_shape_2d.h b/scene/resources/circle_shape_2d.h index e2624ac8ed..8b064f4d9f 100644 --- a/scene/resources/circle_shape_2d.h +++ b/scene/resources/circle_shape_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -50,6 +50,7 @@ public: virtual void draw(const RID &p_to_rid, const Color &p_color); virtual Rect2 get_rect() const; + virtual real_t get_enclosing_radius() const; CircleShape2D(); }; diff --git a/scene/resources/concave_polygon_shape.cpp b/scene/resources/concave_polygon_shape.cpp index dbc07ef591..0a93f99ea3 100644 --- a/scene/resources/concave_polygon_shape.cpp +++ b/scene/resources/concave_polygon_shape.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -64,6 +64,16 @@ Vector<Vector3> ConcavePolygonShape::get_debug_mesh_lines() { return points; } +real_t ConcavePolygonShape::get_enclosing_radius() const { + PoolVector<Vector3> data = get_faces(); + PoolVector<Vector3>::Read read = data.read(); + real_t r = 0; + for (int i(0); i < data.size(); i++) { + r = MAX(read[i].length_squared(), r); + } + return Math::sqrt(r); +} + void ConcavePolygonShape::_update_shape() { Shape::_update_shape(); } diff --git a/scene/resources/concave_polygon_shape.h b/scene/resources/concave_polygon_shape.h index 57362a29be..b4bebbd7b4 100644 --- a/scene/resources/concave_polygon_shape.h +++ b/scene/resources/concave_polygon_shape.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -66,7 +66,8 @@ public: void set_faces(const PoolVector<Vector3> &p_faces); PoolVector<Vector3> get_faces() const; - Vector<Vector3> get_debug_mesh_lines(); + virtual Vector<Vector3> get_debug_mesh_lines(); + virtual real_t get_enclosing_radius() const; ConcavePolygonShape(); }; diff --git a/scene/resources/concave_polygon_shape_2d.cpp b/scene/resources/concave_polygon_shape_2d.cpp index de853f0c30..840733add3 100644 --- a/scene/resources/concave_polygon_shape_2d.cpp +++ b/scene/resources/concave_polygon_shape_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -94,6 +94,16 @@ Rect2 ConcavePolygonShape2D::get_rect() const { return rect; } +real_t ConcavePolygonShape2D::get_enclosing_radius() const { + PoolVector<Vector2> data = get_segments(); + PoolVector<Vector2>::Read read = data.read(); + real_t r = 0; + for (int i(0); i < data.size(); i++) { + r = MAX(read[i].length_squared(), r); + } + return Math::sqrt(r); +} + void ConcavePolygonShape2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_segments", "segments"), &ConcavePolygonShape2D::set_segments); diff --git a/scene/resources/concave_polygon_shape_2d.h b/scene/resources/concave_polygon_shape_2d.h index 8e3267dc2a..4e47ad34b8 100644 --- a/scene/resources/concave_polygon_shape_2d.h +++ b/scene/resources/concave_polygon_shape_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -47,6 +47,7 @@ public: virtual void draw(const RID &p_to_rid, const Color &p_color); virtual Rect2 get_rect() const; + virtual real_t get_enclosing_radius() const; ConcavePolygonShape2D(); }; diff --git a/scene/resources/convex_polygon_shape.cpp b/scene/resources/convex_polygon_shape.cpp index af459ec311..21fdcc1f06 100644 --- a/scene/resources/convex_polygon_shape.cpp +++ b/scene/resources/convex_polygon_shape.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -55,6 +55,16 @@ Vector<Vector3> ConvexPolygonShape::get_debug_mesh_lines() { return Vector<Vector3>(); } +real_t ConvexPolygonShape::get_enclosing_radius() const { + PoolVector<Vector3> data = get_points(); + PoolVector<Vector3>::Read read = data.read(); + real_t r = 0; + for (int i(0); i < data.size(); i++) { + r = MAX(read[i].length_squared(), r); + } + return Math::sqrt(r); +} + void ConvexPolygonShape::_update_shape() { PhysicsServer::get_singleton()->shape_set_data(get_shape(), points); diff --git a/scene/resources/convex_polygon_shape.h b/scene/resources/convex_polygon_shape.h index e6daf1bef4..e3bf02399a 100644 --- a/scene/resources/convex_polygon_shape.h +++ b/scene/resources/convex_polygon_shape.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -48,6 +48,7 @@ public: PoolVector<Vector3> get_points() const; virtual Vector<Vector3> get_debug_mesh_lines(); + virtual real_t get_enclosing_radius() const; ConvexPolygonShape(); }; diff --git a/scene/resources/convex_polygon_shape_2d.cpp b/scene/resources/convex_polygon_shape_2d.cpp index d424fb2814..296d014cc7 100644 --- a/scene/resources/convex_polygon_shape_2d.cpp +++ b/scene/resources/convex_polygon_shape_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -97,6 +97,14 @@ Rect2 ConvexPolygonShape2D::get_rect() const { return rect; } +real_t ConvexPolygonShape2D::get_enclosing_radius() const { + real_t r = 0; + for (int i(0); i < get_points().size(); i++) { + r = MAX(get_points()[i].length_squared(), r); + } + return Math::sqrt(r); +} + ConvexPolygonShape2D::ConvexPolygonShape2D() : Shape2D(Physics2DServer::get_singleton()->convex_polygon_shape_create()) { } diff --git a/scene/resources/convex_polygon_shape_2d.h b/scene/resources/convex_polygon_shape_2d.h index 8625b800ed..83c250c0ce 100644 --- a/scene/resources/convex_polygon_shape_2d.h +++ b/scene/resources/convex_polygon_shape_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -51,6 +51,7 @@ public: virtual void draw(const RID &p_to_rid, const Color &p_color); virtual Rect2 get_rect() const; + virtual real_t get_enclosing_radius() const; ConvexPolygonShape2D(); }; diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index bb14cf3ab1..397f6ca906 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/curve.h b/scene/resources/curve.h index b677097e86..b02466534c 100644 --- a/scene/resources/curve.h +++ b/scene/resources/curve.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/cylinder_shape.cpp b/scene/resources/cylinder_shape.cpp index c1a0a0ac5d..b9b0d77a1b 100644 --- a/scene/resources/cylinder_shape.cpp +++ b/scene/resources/cylinder_shape.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -62,6 +62,10 @@ Vector<Vector3> CylinderShape::get_debug_mesh_lines() { return points; } +real_t CylinderShape::get_enclosing_radius() const { + return Vector2(radius, height * 0.5).length(); +} + void CylinderShape::_update_shape() { Dictionary d; diff --git a/scene/resources/cylinder_shape.h b/scene/resources/cylinder_shape.h index 411c1515ed..a26fda10cd 100644 --- a/scene/resources/cylinder_shape.h +++ b/scene/resources/cylinder_shape.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -50,6 +50,7 @@ public: float get_height() const; virtual Vector<Vector3> get_debug_mesh_lines(); + virtual real_t get_enclosing_radius() const; CylinderShape(); }; diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index e82819f270..00c56e5eb2 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -266,10 +266,10 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // OptionButton - Ref<StyleBox> sb_optbutton_normal = sb_expand(make_stylebox(option_button_normal_png, 4, 4, 21, 4, 6, 3, 21, 3), 2, 2, 2, 2); - Ref<StyleBox> sb_optbutton_pressed = sb_expand(make_stylebox(option_button_pressed_png, 4, 4, 21, 4, 6, 3, 21, 3), 2, 2, 2, 2); - Ref<StyleBox> sb_optbutton_hover = sb_expand(make_stylebox(option_button_hover_png, 4, 4, 21, 4, 6, 2, 21, 2), 2, 2, 2, 2); - Ref<StyleBox> sb_optbutton_disabled = sb_expand(make_stylebox(option_button_disabled_png, 4, 4, 21, 4, 6, 2, 21, 2), 2, 2, 2, 2); + Ref<StyleBox> sb_optbutton_normal = sb_expand(make_stylebox(option_button_normal_png, 4, 4, 21, 4, 6, 3, 9, 3), 2, 2, 2, 2); + Ref<StyleBox> sb_optbutton_pressed = sb_expand(make_stylebox(option_button_pressed_png, 4, 4, 21, 4, 6, 3, 9, 3), 2, 2, 2, 2); + Ref<StyleBox> sb_optbutton_hover = sb_expand(make_stylebox(option_button_hover_png, 4, 4, 21, 4, 6, 2, 9, 2), 2, 2, 2, 2); + Ref<StyleBox> sb_optbutton_disabled = sb_expand(make_stylebox(option_button_disabled_png, 4, 4, 21, 4, 6, 2, 9, 2), 2, 2, 2, 2); Ref<StyleBox> sb_optbutton_focus = sb_expand(make_stylebox(button_focus_png, 4, 4, 4, 4, 6, 2, 6, 2), 2, 2, 2, 2); theme->set_stylebox("normal", "OptionButton", sb_optbutton_normal); @@ -496,9 +496,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_stylebox("slider", "HSlider", make_stylebox(hslider_bg_png, 4, 4, 4, 4)); theme->set_stylebox("grabber_area", "HSlider", make_stylebox(hslider_bg_png, 4, 4, 4, 4)); - theme->set_stylebox("grabber_highlight", "HSlider", make_stylebox(hslider_grabber_hl_png, 6, 6, 6, 6)); - theme->set_stylebox("grabber_disabled", "HSlider", make_stylebox(hslider_grabber_disabled_png, 6, 6, 6, 6)); - theme->set_stylebox("focus", "HSlider", focus); theme->set_icon("grabber", "HSlider", make_icon(hslider_grabber_png)); theme->set_icon("grabber_highlight", "HSlider", make_icon(hslider_grabber_hl_png)); @@ -509,9 +506,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_stylebox("slider", "VSlider", make_stylebox(vslider_bg_png, 4, 4, 4, 4)); theme->set_stylebox("grabber_area", "VSlider", make_stylebox(vslider_bg_png, 4, 4, 4, 4)); - theme->set_stylebox("grabber_highlight", "VSlider", make_stylebox(vslider_grabber_hl_png, 6, 6, 6, 6)); - theme->set_stylebox("grabber_disabled", "VSlider", make_stylebox(vslider_grabber_disabled_png, 6, 6, 6, 6)); - theme->set_stylebox("focus", "VSlider", focus); theme->set_icon("grabber", "VSlider", make_icon(vslider_grabber_png)); theme->set_icon("grabber_highlight", "VSlider", make_icon(vslider_grabber_hl_png)); @@ -653,8 +647,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_color("title_button_color", "Tree", control_font_color); theme->set_color("font_color", "Tree", control_font_color_low); theme->set_color("font_color_selected", "Tree", control_font_color_pressed); - theme->set_color("selection_color", "Tree", Color(0.1, 0.1, 1, 0.8)); - theme->set_color("cursor_color", "Tree", Color(0, 0, 0)); theme->set_color("guide_color", "Tree", Color(0, 0, 0, 0.1)); theme->set_color("drop_position_color", "Tree", Color(1, 0.3, 0.2)); theme->set_color("relationship_line_color", "Tree", Color(0.27, 0.27, 0.27)); @@ -857,6 +849,8 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_stylebox("bg", "GraphEdit", make_stylebox(tree_bg_png, 4, 4, 4, 5)); theme->set_color("grid_minor", "GraphEdit", Color(1, 1, 1, 0.05)); theme->set_color("grid_major", "GraphEdit", Color(1, 1, 1, 0.2)); + theme->set_color("selection_fill", "GraphEdit", Color(1, 1, 1, 0.3)); + theme->set_color("selection_stroke", "GraphEdit", Color(1, 1, 1, 0.8)); theme->set_color("activity", "GraphEdit", Color(1, 1, 1)); theme->set_constant("bezier_len_pos", "GraphEdit", 80 * scale); theme->set_constant("bezier_len_neg", "GraphEdit", 160 * scale); diff --git a/scene/resources/default_theme/default_theme.h b/scene/resources/default_theme/default_theme.h index e7d80ffb3d..1807770ff4 100644 --- a/scene/resources/default_theme/default_theme.h +++ b/scene/resources/default_theme/default_theme.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp index 99a2881d58..451029e93b 100644 --- a/scene/resources/dynamic_font.cpp +++ b/scene/resources/dynamic_font.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -28,8 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef FREETYPE_ENABLED +#include "modules/modules_enabled.gen.h" +#ifdef MODULE_FREETYPE_ENABLED + #include "dynamic_font.h" + #include "core/os/file_access.h" #include "core/os/os.h" @@ -130,7 +133,10 @@ Error DynamicFontAtSize::_load() { } else { FileAccess *f = FileAccess::open(font->font_path, FileAccess::READ); - ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, "Cannot open font file '" + font->font_path + "'."); + if (!f) { + FT_Done_FreeType(library); + ERR_FAIL_V_MSG(ERR_CANT_OPEN, "Cannot open font file '" + font->font_path + "'."); + } size_t len = f->get_len(); _fontdata[font->font_path] = Vector<uint8_t>(); @@ -145,7 +151,10 @@ Error DynamicFontAtSize::_load() { if (font->font_mem == NULL && font->font_path != String()) { FileAccess *f = FileAccess::open(font->font_path, FileAccess::READ); - ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, "Cannot open font file '" + font->font_path + "'."); + if (!f) { + FT_Done_FreeType(library); + ERR_FAIL_V_MSG(ERR_CANT_OPEN, "Cannot open font file '" + font->font_path + "'."); + } memset(&stream, 0, sizeof(FT_StreamRec)); stream.base = NULL; @@ -176,6 +185,7 @@ Error DynamicFontAtSize::_load() { error = FT_Open_Face(library, &fargs, 0, &face); } else { + FT_Done_FreeType(library); ERR_FAIL_V_MSG(ERR_UNCONFIGURED, "DynamicFont uninitialized."); } @@ -195,13 +205,13 @@ Error DynamicFontAtSize::_load() { if (FT_HAS_COLOR(face) && face->num_fixed_sizes > 0) { int best_match = 0; int diff = ABS(id.size - ((int64_t)face->available_sizes[0].width)); - scale_color_font = float(id.size) / face->available_sizes[0].width; + scale_color_font = float(id.size * oversampling) / face->available_sizes[0].width; for (int i = 1; i < face->num_fixed_sizes; i++) { int ndiff = ABS(id.size - ((int64_t)face->available_sizes[i].width)); if (ndiff < diff) { best_match = i; diff = ndiff; - scale_color_font = float(id.size) / face->available_sizes[i].width; + scale_color_font = float(id.size * oversampling) / face->available_sizes[i].width; } } FT_Select_Size(face, best_match); @@ -299,7 +309,7 @@ void DynamicFontAtSize::set_texture_flags(uint32_t p_flags) { } } -float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize> > &p_fallbacks, bool p_advance_only) const { +float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize> > &p_fallbacks, bool p_advance_only, bool p_outline) const { if (!valid) return 0; @@ -314,6 +324,20 @@ float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharT float advance = 0.0; + // use normal character size if there's no outline character + if (p_outline && !ch->found) { + FT_GlyphSlot slot = face->glyph; + int error = FT_Load_Char(face, p_char, FT_HAS_COLOR(face) ? FT_LOAD_COLOR : FT_LOAD_DEFAULT); + if (!error) { + error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL); + if (!error) { + Character character = Character::not_found(); + character = const_cast<DynamicFontAtSize *>(this)->_bitmap_to_character(slot->bitmap, slot->bitmap_top, slot->bitmap_left, slot->advance.x / 64.0); + advance = character.advance; + } + } + } + if (ch->found) { ERR_FAIL_COND_V(ch->texture_idx < -1 || ch->texture_idx >= font->textures.size(), 0); @@ -657,6 +681,7 @@ void DynamicFont::_reload_cache() { if (!data.is_valid()) { data_at_size.unref(); outline_data_at_size.unref(); + fallbacks.resize(0); fallback_data_at_size.resize(0); fallback_outline_data_at_size.resize(0); return; @@ -874,7 +899,7 @@ float DynamicFont::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_ // If requested outline draw, but no outline is present, simply return advance without drawing anything bool advance_only = p_outline && outline_cache_id.outline_size == 0; - return font_at_size->draw_char(p_canvas_item, p_pos, p_char, p_next, color, fallbacks, advance_only) + spacing_char; + return font_at_size->draw_char(p_canvas_item, p_pos, p_char, p_next, color, fallbacks, advance_only, p_outline) + spacing_char; } void DynamicFont::set_fallback(int p_idx, const Ref<DynamicFontData> &p_data) { @@ -996,8 +1021,8 @@ void DynamicFont::_bind_methods() { ClassDB::bind_method(D_METHOD("get_fallback_count"), &DynamicFont::get_fallback_count); ADD_GROUP("Settings", ""); - ADD_PROPERTY(PropertyInfo(Variant::INT, "size", PROPERTY_HINT_RANGE, "1,255,1"), "set_size", "get_size"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "outline_size", PROPERTY_HINT_RANGE, "0,255,1"), "set_outline_size", "get_outline_size"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "size", PROPERTY_HINT_RANGE, "1,1024,1"), "set_size", "get_size"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "outline_size", PROPERTY_HINT_RANGE, "0,1024,1"), "set_outline_size", "get_outline_size"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "outline_color"), "set_outline_color", "get_outline_color"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_mipmaps"), "set_use_mipmaps", "get_use_mipmaps"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_filter"), "set_use_filter", "get_use_filter"); diff --git a/scene/resources/dynamic_font.h b/scene/resources/dynamic_font.h index d0a709a2d3..9170767512 100644 --- a/scene/resources/dynamic_font.h +++ b/scene/resources/dynamic_font.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,9 @@ #ifndef DYNAMIC_FONT_H #define DYNAMIC_FONT_H -#ifdef FREETYPE_ENABLED +#include "modules/modules_enabled.gen.h" +#ifdef MODULE_FREETYPE_ENABLED + #include "core/io/resource_loader.h" #include "core/os/mutex.h" #include "core/os/thread_safe.h" @@ -192,7 +194,7 @@ public: Size2 get_char_size(CharType p_char, CharType p_next, const Vector<Ref<DynamicFontAtSize> > &p_fallbacks) const; - float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize> > &p_fallbacks, bool p_advance_only = false) const; + float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize> > &p_fallbacks, bool p_advance_only = false, bool p_outline = false) const; void set_texture_flags(uint32_t p_flags); void update_oversampling(); diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index bc96b5e9f3..7597cd636e 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -978,7 +978,9 @@ void Environment::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "background_sky", PROPERTY_HINT_RESOURCE_TYPE, "Sky"), "set_sky", "get_sky"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "background_sky_custom_fov", PROPERTY_HINT_RANGE, "0,180,0.1"), "set_sky_custom_fov", "get_sky_custom_fov"); ADD_PROPERTY(PropertyInfo(Variant::BASIS, "background_sky_orientation"), "set_sky_orientation", "get_sky_orientation"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "background_sky_rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_sky_rotation", "get_sky_rotation"); + // Only display rotation in degrees in the inspector (like in Spatial). + // This avoids displaying the same information twice. + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "background_sky_rotation", PROPERTY_HINT_NONE, "", 0), "set_sky_rotation", "get_sky_rotation"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "background_sky_rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_sky_rotation_degrees", "get_sky_rotation_degrees"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "background_color"), "set_bg_color", "get_bg_color"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "background_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_bg_energy", "get_bg_energy"); diff --git a/scene/resources/environment.h b/scene/resources/environment.h index acce9c09a2..62c6c5b4cd 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 124e4d37e6..19c59b3817 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -628,8 +628,8 @@ void BitmapFont::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "chars", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_chars", "_get_chars"); ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "kernings", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_kernings", "_get_kernings"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_RANGE, "-1024,1024,1"), "set_height", "get_height"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ascent", PROPERTY_HINT_RANGE, "-1024,1024,1"), "set_ascent", "get_ascent"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_RANGE, "1,1024,1"), "set_height", "get_height"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "ascent", PROPERTY_HINT_RANGE, "0,1024,1"), "set_ascent", "get_ascent"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "distance_field"), "set_distance_field_hint", "is_distance_field_hint"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "fallback", PROPERTY_HINT_RESOURCE_TYPE, "BitmapFont"), "set_fallback", "get_fallback"); } diff --git a/scene/resources/font.h b/scene/resources/font.h index 9b99b85d22..411145c153 100644 --- a/scene/resources/font.h +++ b/scene/resources/font.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/gradient.cpp b/scene/resources/gradient.cpp index 1ff02c2f82..fe5a01886d 100644 --- a/scene/resources/gradient.cpp +++ b/scene/resources/gradient.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/gradient.h b/scene/resources/gradient.h index 7e7fc99a5d..2d98f799e2 100644 --- a/scene/resources/gradient.h +++ b/scene/resources/gradient.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/height_map_shape.cpp b/scene/resources/height_map_shape.cpp index 214706626d..48c9221e27 100644 --- a/scene/resources/height_map_shape.cpp +++ b/scene/resources/height_map_shape.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -76,6 +76,10 @@ Vector<Vector3> HeightMapShape::get_debug_mesh_lines() { return points; } +real_t HeightMapShape::get_enclosing_radius() const { + return Vector3(real_t(map_width), max_height - min_height, real_t(map_depth)).length(); +} + void HeightMapShape::_update_shape() { Dictionary d; diff --git a/scene/resources/height_map_shape.h b/scene/resources/height_map_shape.h index 4cf2a76213..a6263f061f 100644 --- a/scene/resources/height_map_shape.h +++ b/scene/resources/height_map_shape.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -55,6 +55,7 @@ public: PoolRealArray get_map_data() const; virtual Vector<Vector3> get_debug_mesh_lines(); + virtual real_t get_enclosing_radius() const; HeightMapShape(); }; diff --git a/scene/resources/line_shape_2d.cpp b/scene/resources/line_shape_2d.cpp index f5d5fb561a..d1bb61820b 100644 --- a/scene/resources/line_shape_2d.cpp +++ b/scene/resources/line_shape_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -100,6 +100,10 @@ Rect2 LineShape2D::get_rect() const { return rect; } +real_t LineShape2D::get_enclosing_radius() const { + return d; +} + void LineShape2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_normal", "normal"), &LineShape2D::set_normal); @@ -115,7 +119,7 @@ void LineShape2D::_bind_methods() { LineShape2D::LineShape2D() : Shape2D(Physics2DServer::get_singleton()->line_shape_create()) { - normal = Vector2(0, -1); + normal = Vector2(0, 1); d = 0; _update_shape(); } diff --git a/scene/resources/line_shape_2d.h b/scene/resources/line_shape_2d.h index f684862025..5bf9e85bb9 100644 --- a/scene/resources/line_shape_2d.h +++ b/scene/resources/line_shape_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -55,6 +55,7 @@ public: virtual void draw(const RID &p_to_rid, const Color &p_color); virtual Rect2 get_rect() const; + virtual real_t get_enclosing_radius() const; LineShape2D(); }; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 41bf7f4bf0..ab4dbb758a 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,6 +30,8 @@ #include "material.h" +#include "core/engine.h" + #ifdef TOOLS_ENABLED #include "editor/editor_settings.h" #endif @@ -191,7 +193,10 @@ Variant ShaderMaterial::property_get_revert(const String &p_name) { void ShaderMaterial::set_shader(const Ref<Shader> &p_shader) { - if (shader.is_valid()) { + // Only connect/disconnect the signal when running in the editor. + // This can be a slow operation, and `_change_notify()` (which is called by `_shader_changed()`) + // does nothing in non-editor builds anyway. See GH-34741 for details. + if (shader.is_valid() && Engine::get_singleton()->is_editor_hint()) { shader->disconnect("changed", this, "_shader_changed"); } @@ -200,7 +205,10 @@ void ShaderMaterial::set_shader(const Ref<Shader> &p_shader) { RID rid; if (shader.is_valid()) { rid = shader->get_rid(); - shader->connect("changed", this, "_shader_changed"); + + if (Engine::get_singleton()->is_editor_hint()) { + shader->connect("changed", this, "_shader_changed"); + } } VS::get_singleton()->material_set_shader(_get_material(), rid); diff --git a/scene/resources/material.h b/scene/resources/material.h index 1c69a754b6..8e66011bec 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -42,7 +42,7 @@ class Material : public Resource { GDCLASS(Material, Resource); RES_BASE_EXTENSION("material") - OBJ_SAVE_TYPE(Material) + OBJ_SAVE_TYPE(Material); RID material; Ref<Material> next_pass; @@ -249,10 +249,10 @@ private: uint64_t blend_mode : 2; uint64_t depth_draw_mode : 2; uint64_t cull_mode : 2; - uint64_t flags : 18; + uint64_t flags : 19; uint64_t detail_blend_mode : 2; uint64_t diffuse_mode : 3; - uint64_t specular_mode : 2; + uint64_t specular_mode : 3; uint64_t invalid_key : 1; uint64_t deep_parallax : 1; uint64_t billboard_mode : 2; diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 4afb07cb6f..8f68cc5286 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -75,6 +75,7 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { continue; Array a = surface_get_arrays(i); + ERR_FAIL_COND_V(a.empty(), Ref<TriangleMesh>()); int vc = surface_get_array_len(i); PoolVector<Vector3> vertices = a[ARRAY_VERTEX]; @@ -234,6 +235,7 @@ Ref<Shape> Mesh::create_convex_shape() const { for (int i = 0; i < get_surface_count(); i++) { Array a = surface_get_arrays(i); + ERR_FAIL_COND_V(a.empty(), Ref<ConvexPolygonShape>()); PoolVector<Vector3> v = a[ARRAY_VERTEX]; vertices.append_array(v); } @@ -273,6 +275,7 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { continue; Array a = surface_get_arrays(i); + ERR_FAIL_COND_V(a.empty(), Ref<ArrayMesh>()); if (i == 0) { arrays = a; @@ -378,6 +381,7 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { PoolVector<Vector3>::Write r = vertices.write(); if (indices.size()) { + ERR_FAIL_COND_V(indices.size() % 3 != 0, Ref<ArrayMesh>()); vc = indices.size(); ir = indices.write(); has_indices = true; @@ -483,6 +487,7 @@ void Mesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_lightmap_size_hint", "size"), &Mesh::set_lightmap_size_hint); ClassDB::bind_method(D_METHOD("get_lightmap_size_hint"), &Mesh::get_lightmap_size_hint); + ClassDB::bind_method(D_METHOD("get_aabb"), &Mesh::get_aabb); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "lightmap_size_hint"), "set_lightmap_size_hint", "get_lightmap_size_hint"); @@ -513,7 +518,6 @@ void Mesh::_bind_methods() { BIND_ENUM_CONSTANT(ARRAY_FORMAT_WEIGHTS); BIND_ENUM_CONSTANT(ARRAY_FORMAT_INDEX); - BIND_ENUM_CONSTANT(ARRAY_COMPRESS_BASE); BIND_ENUM_CONSTANT(ARRAY_COMPRESS_VERTEX); BIND_ENUM_CONSTANT(ARRAY_COMPRESS_NORMAL); BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TANGENT); diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index 6b6ee8a209..30ce94f16b 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/mesh_data_tool.cpp b/scene/resources/mesh_data_tool.cpp index 0c39c3cbb1..7a303443e3 100644 --- a/scene/resources/mesh_data_tool.cpp +++ b/scene/resources/mesh_data_tool.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/mesh_data_tool.h b/scene/resources/mesh_data_tool.h index 8f5def72c7..5ac2c7e702 100644 --- a/scene/resources/mesh_data_tool.h +++ b/scene/resources/mesh_data_tool.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/mesh_library.cpp b/scene/resources/mesh_library.cpp index f04af29761..754cad4def 100644 --- a/scene/resources/mesh_library.cpp +++ b/scene/resources/mesh_library.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/mesh_library.h b/scene/resources/mesh_library.h index 4ae4fc6483..5f1fddae22 100644 --- a/scene/resources/mesh_library.h +++ b/scene/resources/mesh_library.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -34,7 +34,7 @@ #include "core/map.h" #include "core/resource.h" #include "mesh.h" -#include "scene/3d/navigation_mesh.h" +#include "scene/3d/navigation_mesh_instance.h" #include "shape.h" class MeshLibrary : public Resource { diff --git a/scene/resources/multimesh.cpp b/scene/resources/multimesh.cpp index 99a17fb5b9..ee831f36f5 100644 --- a/scene/resources/multimesh.cpp +++ b/scene/resources/multimesh.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/multimesh.h b/scene/resources/multimesh.h index 6b17e9278d..9394737799 100644 --- a/scene/resources/multimesh.h +++ b/scene/resources/multimesh.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/navigation_mesh.cpp b/scene/resources/navigation_mesh.cpp index 496dc4b411..e6544778bc 100644 --- a/scene/3d/navigation_mesh.cpp +++ b/scene/resources/navigation_mesh.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,8 +29,6 @@ /*************************************************************************/ #include "navigation_mesh.h" -#include "mesh_instance.h" -#include "navigation.h" void NavigationMesh::create_from_mesh(const Ref<Mesh> &p_mesh) { @@ -548,197 +546,3 @@ NavigationMesh::NavigationMesh() { filter_ledge_spans = false; filter_walkable_low_height_spans = false; } - -void NavigationMeshInstance::set_enabled(bool p_enabled) { - - if (enabled == p_enabled) - return; - enabled = p_enabled; - - if (!is_inside_tree()) - return; - - if (!enabled) { - - if (nav_id != -1) { - navigation->navmesh_remove(nav_id); - nav_id = -1; - } - } else { - - if (navigation) { - - if (navmesh.is_valid()) { - - nav_id = navigation->navmesh_add(navmesh, get_relative_transform(navigation), this); - } - } - } - - if (debug_view) { - MeshInstance *dm = Object::cast_to<MeshInstance>(debug_view); - if (is_enabled()) { - dm->set_material_override(get_tree()->get_debug_navigation_material()); - } else { - dm->set_material_override(get_tree()->get_debug_navigation_disabled_material()); - } - } - - update_gizmo(); -} - -bool NavigationMeshInstance::is_enabled() const { - - return enabled; -} - -///////////////////////////// - -void NavigationMeshInstance::_notification(int p_what) { - - switch (p_what) { - case NOTIFICATION_ENTER_TREE: { - - Spatial *c = this; - while (c) { - - navigation = Object::cast_to<Navigation>(c); - if (navigation) { - - if (enabled && navmesh.is_valid()) { - - nav_id = navigation->navmesh_add(navmesh, get_relative_transform(navigation), this); - } - break; - } - - c = c->get_parent_spatial(); - } - - if (navmesh.is_valid() && get_tree()->is_debugging_navigation_hint()) { - - MeshInstance *dm = memnew(MeshInstance); - dm->set_mesh(navmesh->get_debug_mesh()); - if (is_enabled()) { - dm->set_material_override(get_tree()->get_debug_navigation_material()); - } else { - dm->set_material_override(get_tree()->get_debug_navigation_disabled_material()); - } - add_child(dm); - debug_view = dm; - } - - } break; - case NOTIFICATION_TRANSFORM_CHANGED: { - - if (navigation && nav_id != -1) { - navigation->navmesh_set_transform(nav_id, get_relative_transform(navigation)); - } - - } break; - case NOTIFICATION_EXIT_TREE: { - - if (navigation) { - - if (nav_id != -1) { - navigation->navmesh_remove(nav_id); - nav_id = -1; - } - } - - if (debug_view) { - debug_view->queue_delete(); - debug_view = NULL; - } - navigation = NULL; - } break; - } -} - -void NavigationMeshInstance::set_navigation_mesh(const Ref<NavigationMesh> &p_navmesh) { - - if (p_navmesh == navmesh) - return; - - if (navigation && nav_id != -1) { - navigation->navmesh_remove(nav_id); - nav_id = -1; - } - - if (navmesh.is_valid()) { - navmesh->remove_change_receptor(this); - } - - navmesh = p_navmesh; - - if (navmesh.is_valid()) { - navmesh->add_change_receptor(this); - } - - if (navigation && navmesh.is_valid() && enabled) { - nav_id = navigation->navmesh_add(navmesh, get_relative_transform(navigation), this); - } - - if (debug_view && navmesh.is_valid()) { - Object::cast_to<MeshInstance>(debug_view)->set_mesh(navmesh->get_debug_mesh()); - } - - update_gizmo(); - update_configuration_warning(); -} - -Ref<NavigationMesh> NavigationMeshInstance::get_navigation_mesh() const { - - return navmesh; -} - -String NavigationMeshInstance::get_configuration_warning() const { - - if (!is_visible_in_tree() || !is_inside_tree()) - return String(); - - if (!navmesh.is_valid()) { - return TTR("A NavigationMesh resource must be set or created for this node to work."); - } - const Spatial *c = this; - while (c) { - - if (Object::cast_to<Navigation>(c)) - return String(); - - c = Object::cast_to<Spatial>(c->get_parent()); - } - - return TTR("NavigationMeshInstance must be a child or grandchild to a Navigation node. It only provides navigation data."); -} - -void NavigationMeshInstance::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_navigation_mesh", "navmesh"), &NavigationMeshInstance::set_navigation_mesh); - ClassDB::bind_method(D_METHOD("get_navigation_mesh"), &NavigationMeshInstance::get_navigation_mesh); - - ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationMeshInstance::set_enabled); - ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationMeshInstance::is_enabled); - - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navmesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"), "set_navigation_mesh", "get_navigation_mesh"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled"); -} - -void NavigationMeshInstance::_changed_callback(Object *p_changed, const char *p_prop) { - update_gizmo(); - update_configuration_warning(); -} - -NavigationMeshInstance::NavigationMeshInstance() { - - debug_view = NULL; - navigation = NULL; - nav_id = -1; - enabled = true; - set_notify_transform(true); -} - -NavigationMeshInstance::~NavigationMeshInstance() { - if (navmesh.is_valid()) - navmesh->remove_change_receptor(this); -} diff --git a/scene/3d/navigation_mesh.h b/scene/resources/navigation_mesh.h index d5de653e40..a2b1c62eab 100644 --- a/scene/3d/navigation_mesh.h +++ b/scene/resources/navigation_mesh.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,6 @@ #ifndef NAVIGATION_MESH_H #define NAVIGATION_MESH_H -#include "scene/3d/spatial.h" #include "scene/resources/mesh.h" class Mesh; @@ -193,35 +192,4 @@ public: NavigationMesh(); }; -class Navigation; - -class NavigationMeshInstance : public Spatial { - - GDCLASS(NavigationMeshInstance, Spatial); - - bool enabled; - int nav_id; - Navigation *navigation; - Ref<NavigationMesh> navmesh; - - Node *debug_view; - -protected: - void _notification(int p_what); - static void _bind_methods(); - void _changed_callback(Object *p_changed, const char *p_prop); - -public: - void set_enabled(bool p_enabled); - bool is_enabled() const; - - void set_navigation_mesh(const Ref<NavigationMesh> &p_navmesh); - Ref<NavigationMesh> get_navigation_mesh() const; - - String get_configuration_warning() const; - - NavigationMeshInstance(); - ~NavigationMeshInstance(); -}; - #endif // NAVIGATION_MESH_H diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index 7d62873bbd..3e7d350eec 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -39,7 +39,7 @@ #include "scene/gui/control.h" #include "scene/main/instance_placeholder.h" -#define PACK_VERSION 2 +#define PACKED_SCENE_VERSION 2 bool SceneState::can_instance() const { @@ -397,6 +397,9 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map if (p_owner->get_scene_inherited_state().is_null() && (p_node == p_owner || (p_node->get_owner() == p_owner && (p_node->get_parent() == p_owner || p_node->get_parent()->get_owner() == p_owner)))) { //do not save index, because it belongs to saved scene and scene is not inherited nd.index = -1; + } else if (p_node == p_owner) { + //This (hopefully) happens if the node is a scene root, so its index is irrelevant. + nd.index = -1; } else { //part of an inherited scene, or parent is from an instanced scene nd.index = p_node->get_index(); @@ -1092,7 +1095,15 @@ void SceneState::set_bundled_scene(const Dictionary &p_dictionary) { if (p_dictionary.has("version")) version = p_dictionary["version"]; - ERR_FAIL_COND_MSG(version > PACK_VERSION, "Save format version too new."); + ERR_FAIL_COND_MSG(version > PACKED_SCENE_VERSION, "Save format version too new."); + + const int node_count = p_dictionary["node_count"]; + const PoolVector<int> snodes = p_dictionary["nodes"]; + ERR_FAIL_COND(snodes.size() < node_count); + + const int conn_count = p_dictionary["conn_count"]; + const PoolVector<int> sconns = p_dictionary["conns"]; + ERR_FAIL_COND(sconns.size() < conn_count); PoolVector<String> snames = p_dictionary["names"]; if (snames.size()) { @@ -1118,13 +1129,11 @@ void SceneState::set_bundled_scene(const Dictionary &p_dictionary) { variants.clear(); } - nodes.resize(p_dictionary["node_count"]); - int nc = nodes.size(); - if (nc) { - PoolVector<int> snodes = p_dictionary["nodes"]; + nodes.resize(node_count); + if (node_count) { PoolVector<int>::Read r = snodes.read(); int idx = 0; - for (int i = 0; i < nc; i++) { + for (int i = 0; i < node_count; i++) { NodeData &nd = nodes.write[i]; nd.parent = r[idx++]; nd.owner = r[idx++]; @@ -1148,15 +1157,11 @@ void SceneState::set_bundled_scene(const Dictionary &p_dictionary) { } } - connections.resize(p_dictionary["conn_count"]); - int cc = connections.size(); - - if (cc) { - - PoolVector<int> sconns = p_dictionary["conns"]; + connections.resize(conn_count); + if (conn_count) { PoolVector<int>::Read r = sconns.read(); int idx = 0; - for (int i = 0; i < cc; i++) { + for (int i = 0; i < conn_count; i++) { ConnectionData &cd = connections.write[i]; cd.from = r[idx++]; cd.to = r[idx++]; @@ -1280,9 +1285,7 @@ Dictionary SceneState::get_bundled_scene() const { d["base_scene"] = base_scene_idx; } - d["version"] = PACK_VERSION; - - //d["path"]=path; + d["version"] = PACKED_SCENE_VERSION; return d; } diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h index 3c05929dea..b4966e2528 100644 --- a/scene/resources/packed_scene.h +++ b/scene/resources/packed_scene.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp index c5956d9bc2..baeb88400e 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particles_material.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -198,6 +198,9 @@ void ParticlesMaterial::_update_shader() { code += "uniform sampler2D emission_texture_color : hint_white;\n"; } } break; + case EMISSION_SHAPE_MAX: { // Max value for validity check. + break; + } } code += "uniform vec4 color_value : hint_color;\n"; @@ -283,7 +286,7 @@ void ParticlesMaterial::_update_shader() { code += " float degree_to_rad = pi / 180.0;\n"; code += "\n"; - if (emission_shape >= EMISSION_SHAPE_POINTS) { + if (emission_shape == EMISSION_SHAPE_POINTS || emission_shape == EMISSION_SHAPE_DIRECTED_POINTS) { code += " int point = min(emission_texture_point_count - 1, int(rand_from_seed(alt_seed) * float(emission_texture_point_count)));\n"; code += " ivec2 emission_tex_size = textureSize(emission_texture_points, 0);\n"; code += " ivec2 emission_tex_ofs = ivec2(point % emission_tex_size.x, point / emission_tex_size.x);\n"; @@ -313,14 +316,17 @@ void ParticlesMaterial::_update_shader() { if (flags[FLAG_DISABLE_Z]) { - code += " float angle1_rad = atan(direction.y, direction.x) + rand_from_seed_m1_p1(alt_seed) * spread_rad;\n"; + code += " float angle1_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad;\n"; + code += " angle1_rad += direction.x != 0.0 ? atan(direction.y, direction.x) : sign(direction.y) * (pi / 2.0);\n"; code += " vec3 rot = vec3(cos(angle1_rad), sin(angle1_rad), 0.0);\n"; code += " VELOCITY = rot * initial_linear_velocity * mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; } else { //initiate velocity spread in 3D - code += " float angle1_rad = atan(direction.x, direction.z) + rand_from_seed_m1_p1(alt_seed) * spread_rad;\n"; - code += " float angle2_rad = atan(direction.y, abs(direction.z)) + rand_from_seed_m1_p1(alt_seed) * spread_rad * (1.0 - flatness);\n"; + code += " float angle1_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad;\n"; + code += " float angle2_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad * (1.0 - flatness);\n"; + code += " angle1_rad += direction.z != 0.0 ? atan(direction.x, direction.z) : sign(direction.x) * (pi / 2.0);\n"; + code += " angle2_rad += direction.z != 0.0 ? atan(direction.y, abs(direction.z)) : (direction.x != 0.0 ? atan(direction.y, abs(direction.x)) : sign(direction.y) * (pi / 2.0));\n"; code += " vec3 direction_xz = vec3(sin(angle1_rad), 0.0, cos(angle1_rad));\n"; code += " vec3 direction_yz = vec3(0.0, sin(angle2_rad), cos(angle2_rad));\n"; code += " direction_yz.z = direction_yz.z / max(0.0001,sqrt(abs(direction_yz.z))); // better uniform distribution\n"; @@ -368,6 +374,9 @@ void ParticlesMaterial::_update_shader() { } } } break; + case EMISSION_SHAPE_MAX: { // Max value for validity check. + break; + } } code += " VELOCITY = (EMISSION_TRANSFORM * vec4(VELOCITY, 0.0)).xyz;\n"; code += " TRANSFORM = EMISSION_TRANSFORM * TRANSFORM;\n"; @@ -515,7 +524,7 @@ void ParticlesMaterial::_update_shader() { } else { code += " COLOR = hue_rot_mat * color_value;\n"; } - if (emission_color_texture.is_valid() && emission_shape >= EMISSION_SHAPE_POINTS) { + if (emission_color_texture.is_valid() && (emission_shape == EMISSION_SHAPE_POINTS || emission_shape == EMISSION_SHAPE_DIRECTED_POINTS)) { code += " COLOR *= texelFetch(emission_texture_color, emission_tex_ofs, 0);\n"; } if (trail_color_modifier.is_valid()) { @@ -894,7 +903,7 @@ bool ParticlesMaterial::get_flag(Flags p_flag) const { } void ParticlesMaterial::set_emission_shape(EmissionShape p_shape) { - + ERR_FAIL_INDEX(p_shape, EMISSION_SHAPE_MAX); emission_shape = p_shape; _change_notify(); _queue_shader_change(); @@ -1242,6 +1251,7 @@ void ParticlesMaterial::_bind_methods() { BIND_ENUM_CONSTANT(EMISSION_SHAPE_BOX); BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINTS); BIND_ENUM_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS); + BIND_ENUM_CONSTANT(EMISSION_SHAPE_MAX); } ParticlesMaterial::ParticlesMaterial() : diff --git a/scene/resources/particles_material.h b/scene/resources/particles_material.h index 6fe381db0a..cc860b3812 100644 --- a/scene/resources/particles_material.h +++ b/scene/resources/particles_material.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -69,6 +69,7 @@ public: EMISSION_SHAPE_BOX, EMISSION_SHAPE_POINTS, EMISSION_SHAPE_DIRECTED_POINTS, + EMISSION_SHAPE_MAX }; private: diff --git a/scene/resources/physics_material.cpp b/scene/resources/physics_material.cpp index 7d97c279ed..0db115ecc0 100644 --- a/scene/resources/physics_material.cpp +++ b/scene/resources/physics_material.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/physics_material.h b/scene/resources/physics_material.h index 30660e80ac..2f7f4424b2 100644 --- a/scene/resources/physics_material.h +++ b/scene/resources/physics_material.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/plane_shape.cpp b/scene/resources/plane_shape.cpp index d3274ec5f8..ddc820233e 100644 --- a/scene/resources/plane_shape.cpp +++ b/scene/resources/plane_shape.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/plane_shape.h b/scene/resources/plane_shape.h index f853d1966b..360f9dbbe9 100644 --- a/scene/resources/plane_shape.h +++ b/scene/resources/plane_shape.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -47,6 +47,10 @@ public: Plane get_plane() const; virtual Vector<Vector3> get_debug_mesh_lines(); + virtual real_t get_enclosing_radius() const { + // Should be infinite? + return 0; + } PlaneShape(); }; diff --git a/scene/resources/polygon_path_finder.cpp b/scene/resources/polygon_path_finder.cpp index bd3236cb5b..9a1d478777 100644 --- a/scene/resources/polygon_path_finder.cpp +++ b/scene/resources/polygon_path_finder.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/polygon_path_finder.h b/scene/resources/polygon_path_finder.h index 59387e9672..2ef5c89e2a 100644 --- a/scene/resources/polygon_path_finder.h +++ b/scene/resources/polygon_path_finder.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index 24fdaafbe1..74df72619a 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h index fad49f9642..47126f1862 100644 --- a/scene/resources/primitive_meshes.h +++ b/scene/resources/primitive_meshes.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/ray_shape.cpp b/scene/resources/ray_shape.cpp index f185263a36..1a9b7e6dd2 100644 --- a/scene/resources/ray_shape.cpp +++ b/scene/resources/ray_shape.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -41,6 +41,10 @@ Vector<Vector3> RayShape::get_debug_mesh_lines() { return points; } +real_t RayShape::get_enclosing_radius() const { + return length; +} + void RayShape::_update_shape() { Dictionary d; diff --git a/scene/resources/ray_shape.h b/scene/resources/ray_shape.h index fee7475c69..c89705ad7d 100644 --- a/scene/resources/ray_shape.h +++ b/scene/resources/ray_shape.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -50,6 +50,7 @@ public: bool get_slips_on_slope() const; virtual Vector<Vector3> get_debug_mesh_lines(); + virtual real_t get_enclosing_radius() const; RayShape(); }; diff --git a/scene/resources/rectangle_shape_2d.cpp b/scene/resources/rectangle_shape_2d.cpp index ff0743a8dd..f8c8ffb289 100644 --- a/scene/resources/rectangle_shape_2d.cpp +++ b/scene/resources/rectangle_shape_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -59,6 +59,10 @@ Rect2 RectangleShape2D::get_rect() const { return Rect2(-extents, extents * 2.0); } +real_t RectangleShape2D::get_enclosing_radius() const { + return extents.length(); +} + void RectangleShape2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_extents", "extents"), &RectangleShape2D::set_extents); diff --git a/scene/resources/rectangle_shape_2d.h b/scene/resources/rectangle_shape_2d.h index 27305e5918..68fc539085 100644 --- a/scene/resources/rectangle_shape_2d.h +++ b/scene/resources/rectangle_shape_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -48,6 +48,7 @@ public: virtual void draw(const RID &p_to_rid, const Color &p_color); virtual Rect2 get_rect() const; + virtual real_t get_enclosing_radius() const; RectangleShape2D(); }; diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp index baffc1396d..849fb087ba 100644 --- a/scene/resources/resource_format_text.cpp +++ b/scene/resources/resource_format_text.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -1384,7 +1384,7 @@ void ResourceFormatSaverTextInstance::_find_resources(const Variant &p_variant, if (!p_main && (!bundle_resources) && res->get_path().length() && res->get_path().find("::") == -1) { if (res->get_path() == local_path) { - ERR_PRINTS("Circular reference to resource being saved found: '" + local_path + "' will be null next time it's loaded."); + ERR_PRINT("Circular reference to resource being saved found: '" + local_path + "' will be null next time it's loaded."); return; } int index = external_resources.size(); @@ -1459,20 +1459,6 @@ void ResourceFormatSaverTextInstance::_find_resources(const Variant &p_variant, } } -static String _valprop(const String &p_name) { - - // Escape and quote strings with extended ASCII or further Unicode characters - // as well as '"', '=' or ' ' (32) - const CharType *cstr = p_name.c_str(); - for (int i = 0; cstr[i]; i++) { - if (cstr[i] == '=' || cstr[i] == '"' || cstr[i] < 33 || cstr[i] > 126) { - return "\"" + p_name.c_escape_multiline() + "\""; - } - } - // Keep as is - return p_name; -} - Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { if (p_path.ends_with(".tscn")) { @@ -1675,7 +1661,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r String vars; VariantWriter::write_to_string(value, vars, _write_resources, this); - f->store_string(_valprop(name) + " = " + vars + "\n"); + f->store_string(name.property_name_encode() + " = " + vars + "\n"); } } @@ -1747,7 +1733,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r String vars; VariantWriter::write_to_string(state->get_node_property_value(i, j), vars, _write_resources, this); - f->store_string(_valprop(String(state->get_node_property_name(i, j))) + " = " + vars + "\n"); + f->store_string(String(state->get_node_property_name(i, j)).property_name_encode() + " = " + vars + "\n"); } if (i < state->get_node_count() - 1) diff --git a/scene/resources/resource_format_text.h b/scene/resources/resource_format_text.h index 0041989f09..66c69725e8 100644 --- a/scene/resources/resource_format_text.h +++ b/scene/resources/resource_format_text.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/room.cpp b/scene/resources/room.cpp deleted file mode 100644 index 103a7ede74..0000000000 --- a/scene/resources/room.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/*************************************************************************/ -/* room.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "room.h" - -#include "servers/visual_server.h" - -// FIXME: Left for reference for reimplementation using Area -#if 0 -RID RoomBounds::get_rid() const { - - return area; -} - -void RoomBounds::set_geometry_hint(const PoolVector<Face3> &p_geometry_hint) { - - geometry_hint = p_geometry_hint; -} - -PoolVector<Face3> RoomBounds::get_geometry_hint() const { - - return geometry_hint; -} - -void RoomBounds::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_geometry_hint", "triangles"), &RoomBounds::set_geometry_hint); - ClassDB::bind_method(D_METHOD("get_geometry_hint"), &RoomBounds::get_geometry_hint); - - //ADD_PROPERTY( PropertyInfo( Variant::DICTIONARY, "bounds"), "set_bounds","get_bounds") ; - ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR3_ARRAY, "geometry_hint"), "set_geometry_hint", "get_geometry_hint"); -} - -RoomBounds::RoomBounds() { - - area = VisualServer::get_singleton()->room_create(); -} - -RoomBounds::~RoomBounds() { - - VisualServer::get_singleton()->free(area); -} -#endif diff --git a/scene/resources/segment_shape_2d.cpp b/scene/resources/segment_shape_2d.cpp index 62c5f9bab3..3094d0f9bd 100644 --- a/scene/resources/segment_shape_2d.cpp +++ b/scene/resources/segment_shape_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -82,6 +82,10 @@ Rect2 SegmentShape2D::get_rect() const { return rect; } +real_t SegmentShape2D::get_enclosing_radius() const { + return (a + b).length(); +} + void SegmentShape2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_a", "a"), &SegmentShape2D::set_a); @@ -120,8 +124,8 @@ void RayShape2D::draw(const RID &p_to_rid, const Color &p_color) { Vector<Vector2> pts; float tsize = 4; pts.push_back(tip + Vector2(0, tsize)); - pts.push_back(tip + Vector2(0.707 * tsize, 0)); - pts.push_back(tip + Vector2(-0.707 * tsize, 0)); + pts.push_back(tip + Vector2(Math_SQRT12 * tsize, 0)); + pts.push_back(tip + Vector2(-Math_SQRT12 * tsize, 0)); Vector<Color> cols; for (int i = 0; i < 3; i++) cols.push_back(p_color); @@ -134,10 +138,14 @@ Rect2 RayShape2D::get_rect() const { Rect2 rect; rect.position = Vector2(); rect.expand_to(Vector2(0, length)); - rect = rect.grow(0.707 * 4); + rect = rect.grow(Math_SQRT12 * 4); return rect; } +real_t RayShape2D::get_enclosing_radius() const { + return length; +} + void RayShape2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_length", "length"), &RayShape2D::set_length); diff --git a/scene/resources/segment_shape_2d.h b/scene/resources/segment_shape_2d.h index f35707b990..ca10c24f07 100644 --- a/scene/resources/segment_shape_2d.h +++ b/scene/resources/segment_shape_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -55,6 +55,7 @@ public: virtual void draw(const RID &p_to_rid, const Color &p_color); virtual Rect2 get_rect() const; + virtual real_t get_enclosing_radius() const; SegmentShape2D(); }; @@ -79,6 +80,7 @@ public: virtual void draw(const RID &p_to_rid, const Color &p_color); virtual Rect2 get_rect() const; + virtual real_t get_enclosing_radius() const; RayShape2D(); }; diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index 57e2470164..44c2a46065 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/shader.h b/scene/resources/shader.h index 6e7447839f..67ae436a4c 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/shape.cpp b/scene/resources/shape.cpp index 3500fdb4bc..b50c68727a 100644 --- a/scene/resources/shape.cpp +++ b/scene/resources/shape.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/shape.h b/scene/resources/shape.h index 2743fd0c65..227a581c96 100644 --- a/scene/resources/shape.h +++ b/scene/resources/shape.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,6 +32,7 @@ #define SHAPE_H #include "core/resource.h" + class ArrayMesh; class Shape : public Resource { @@ -57,6 +58,8 @@ public: Ref<ArrayMesh> get_debug_mesh(); virtual Vector<Vector3> get_debug_mesh_lines() = 0; // { return Vector<Vector3>(); } + /// Returns the radius of a sphere that fully enclose this shape + virtual real_t get_enclosing_radius() const = 0; void add_vertices_to_array(PoolVector<Vector3> &array, const Transform &p_xform); diff --git a/scene/resources/shape_2d.cpp b/scene/resources/shape_2d.cpp index e2407e4423..9e97c65a3c 100644 --- a/scene/resources/shape_2d.cpp +++ b/scene/resources/shape_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/shape_2d.h b/scene/resources/shape_2d.h index da9b80477c..e2933ec031 100644 --- a/scene/resources/shape_2d.h +++ b/scene/resources/shape_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -58,6 +58,8 @@ public: virtual void draw(const RID &p_to_rid, const Color &p_color) {} virtual Rect2 get_rect() const { return Rect2(); } + /// Returns the radius of a circle that fully enclose this shape + virtual real_t get_enclosing_radius() const = 0; virtual RID get_rid() const; Shape2D(); ~Shape2D(); diff --git a/scene/resources/skin.cpp b/scene/resources/skin.cpp index 98c114e0e6..9c8710a59c 100644 --- a/scene/resources/skin.cpp +++ b/scene/resources/skin.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/skin.h b/scene/resources/skin.h index 7dd02eca5d..ddc7c655f5 100644 --- a/scene/resources/skin.h +++ b/scene/resources/skin.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/sky.cpp b/scene/resources/sky.cpp index 292fdcdbd2..c20fbb4129 100644 --- a/scene/resources/sky.cpp +++ b/scene/resources/sky.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/sky.h b/scene/resources/sky.h index 3a6f44e11b..70ea9c4c18 100644 --- a/scene/resources/sky.h +++ b/scene/resources/sky.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/space_2d.cpp b/scene/resources/space_2d.cpp index e6d366c501..376e926548 100644 --- a/scene/resources/space_2d.cpp +++ b/scene/resources/space_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/space_2d.h b/scene/resources/space_2d.h index ced7c87406..ff88c40348 100644 --- a/scene/resources/space_2d.h +++ b/scene/resources/space_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/sphere_shape.cpp b/scene/resources/sphere_shape.cpp index 019bc9189a..56121b6941 100644 --- a/scene/resources/sphere_shape.cpp +++ b/scene/resources/sphere_shape.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -55,6 +55,10 @@ Vector<Vector3> SphereShape::get_debug_mesh_lines() { return points; } +real_t SphereShape::get_enclosing_radius() const { + return radius; +} + void SphereShape::_update_shape() { PhysicsServer::get_singleton()->shape_set_data(get_shape(), radius); diff --git a/scene/resources/sphere_shape.h b/scene/resources/sphere_shape.h index 679882fe23..07e8f1e233 100644 --- a/scene/resources/sphere_shape.h +++ b/scene/resources/sphere_shape.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -48,6 +48,7 @@ public: float get_radius() const; virtual Vector<Vector3> get_debug_mesh_lines(); + virtual real_t get_enclosing_radius() const; SphereShape(); }; diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp index d56360f918..9408d1aa71 100644 --- a/scene/resources/style_box.cpp +++ b/scene/resources/style_box.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -81,6 +81,10 @@ Size2 StyleBox::get_center_size() const { return Size2(); } +Rect2 StyleBox::get_draw_rect(const Rect2 &p_rect) const { + return p_rect; +} + void StyleBox::_bind_methods() { ClassDB::bind_method(D_METHOD("test_mask", "point", "rect"), &StyleBox::test_mask); @@ -175,6 +179,10 @@ float StyleBoxTexture::get_style_margin(Margin p_margin) const { return margin[p_margin]; } +Rect2 StyleBoxTexture::get_draw_rect(const Rect2 &p_rect) const { + return p_rect.grow_individual(expand_margin[MARGIN_LEFT], expand_margin[MARGIN_TOP], expand_margin[MARGIN_RIGHT], expand_margin[MARGIN_BOTTOM]); +} + void StyleBoxTexture::draw(RID p_canvas_item, const Rect2 &p_rect) const { if (texture.is_null()) return; @@ -546,7 +554,7 @@ int StyleBoxFlat::get_aa_size() const { } void StyleBoxFlat::set_corner_detail(const int &p_corner_detail) { - corner_detail = CLAMP(p_corner_detail, 1, 128); + corner_detail = CLAMP(p_corner_detail, 1, 20); emit_changed(); } int StyleBoxFlat::get_corner_detail() const { @@ -582,8 +590,8 @@ inline void set_inner_corner_radius(const Rect2 style_rect, const Rect2 inner_re inner_corner_radius[3] = MAX(corner_radius[3] - rad, 0); } -inline void draw_ring(Vector<Vector2> &verts, Vector<int> &indices, Vector<Color> &colors, const Rect2 style_rect, const int corner_radius[4], - const Rect2 ring_rect, const int border_width[4], const Color &inner_color, const Color &outer_color, const int corner_detail, const bool fill_center = false) { +inline void draw_ring(Vector<Vector2> &verts, Vector<int> &indices, Vector<Color> &colors, const Rect2 &style_rect, const int corner_radius[4], + const Rect2 &ring_rect, const Rect2 &inner_rect, const Color &inner_color, const Color &outer_color, const int corner_detail, const bool fill_center = false) { int vert_offset = verts.size(); if (!vert_offset) { @@ -602,9 +610,6 @@ inline void draw_ring(Vector<Vector2> &verts, Vector<int> &indices, Vector<Color outer_points.push_back(ring_rect.position + ring_rect.size - Vector2(ring_corner_radius[2], ring_corner_radius[2])); //br outer_points.push_back(Point2(ring_rect.position.x + ring_corner_radius[3], ring_rect.position.y + ring_rect.size.y - ring_corner_radius[3])); //bl - Rect2 inner_rect; - inner_rect = ring_rect.grow_individual(-border_width[MARGIN_LEFT], -border_width[MARGIN_TOP], -border_width[MARGIN_RIGHT], -border_width[MARGIN_BOTTOM]); - int inner_corner_radius[4]; set_inner_corner_radius(style_rect, inner_rect, corner_radius, inner_corner_radius); @@ -685,6 +690,19 @@ inline void adapt_values(int p_index_a, int p_index_b, int *adapted_values, cons adapted_values[p_index_a] = MIN(p_max_a, adapted_values[p_index_a]); adapted_values[p_index_b] = MIN(p_max_b, adapted_values[p_index_b]); } + +Rect2 StyleBoxFlat::get_draw_rect(const Rect2 &p_rect) const { + Rect2 draw_rect = p_rect.grow_individual(expand_margin[MARGIN_LEFT], expand_margin[MARGIN_TOP], expand_margin[MARGIN_RIGHT], expand_margin[MARGIN_BOTTOM]); + + if (shadow_size > 0) { + Rect2 shadow_rect = draw_rect.grow(shadow_size); + shadow_rect.position += shadow_offset; + draw_rect = draw_rect.merge(shadow_rect); + } + + return draw_rect; +} + void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const { //PREPARATIONS @@ -701,21 +719,13 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const { bool rounded_corners = (corner_radius[0] > 0) || (corner_radius[1] > 0) || (corner_radius[2] > 0) || (corner_radius[3] > 0); bool aa_on = rounded_corners && anti_aliased; - - Color border_color_alpha = Color(border_color.r, border_color.g, border_color.b, 0); + float aa_size_grow = 0.5 * ((float)aa_size + 1.0); bool blend_on = blend_border && draw_border; - Rect2 border_style_rect = style_rect; - if (aa_on && !blend_on) { - float aa_size_grow = 0.5 * ((aa_size + 1) / 2); - style_rect = style_rect.grow(-aa_size_grow); - for (int i = 0; i < 4; i++) { - if (border_width[i] > 0) { - border_style_rect = border_style_rect.grow_margin((Margin)i, -aa_size_grow); - } - } - } + Color border_color_alpha = Color(border_color.r, border_color.g, border_color.b, 0); + Color border_color_blend = (draw_center ? bg_color : border_color_alpha); + Color border_color_inner = blend_on ? border_color_blend : border_color; //adapt borders (prevent weird overlapping/glitchy drawings) int width = MAX(style_rect.size.width, 0); @@ -733,6 +743,15 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const { Rect2 infill_rect = style_rect.grow_individual(-adapted_border[MARGIN_LEFT], -adapted_border[MARGIN_TOP], -adapted_border[MARGIN_RIGHT], -adapted_border[MARGIN_BOTTOM]); + Rect2 border_style_rect = style_rect; + if (aa_on) { + for (int i = 0; i < 4; i++) { + if (border_width[i] > 0) { + border_style_rect = border_style_rect.grow_margin((Margin)i, -aa_size_grow); + } + } + } + Vector<Point2> verts; Vector<int> indices; Vector<Color> colors; @@ -740,8 +759,6 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const { //DRAW SHADOW if (draw_shadow) { - int shadow_width[4] = { shadow_size, shadow_size, shadow_size, shadow_size }; - Rect2 shadow_inner_rect = style_rect; shadow_inner_rect.position += shadow_offset; @@ -751,59 +768,65 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const { Color shadow_color_transparent = Color(shadow_color.r, shadow_color.g, shadow_color.b, 0); draw_ring(verts, indices, colors, shadow_inner_rect, adapted_corner, - shadow_rect, shadow_width, shadow_color, shadow_color_transparent, corner_detail); + shadow_rect, shadow_inner_rect, shadow_color, shadow_color_transparent, corner_detail); if (draw_center) { - int no_border[4] = { 0, 0, 0, 0 }; draw_ring(verts, indices, colors, shadow_inner_rect, adapted_corner, - shadow_inner_rect, no_border, shadow_color, shadow_color, corner_detail, true); + shadow_inner_rect, shadow_inner_rect, shadow_color, shadow_color, corner_detail, true); } } //DRAW border if (draw_border) { draw_ring(verts, indices, colors, border_style_rect, adapted_corner, - border_style_rect, adapted_border, blend_on ? (draw_center ? bg_color : border_color_alpha) : border_color, border_color, corner_detail); + border_style_rect, infill_rect, border_color_inner, border_color, corner_detail); } //DRAW INFILL - if (draw_center) { - int no_border[4] = { 0, 0, 0, 0 }; - draw_ring(verts, indices, colors, style_rect, adapted_corner, - infill_rect, no_border, bg_color, bg_color, corner_detail, true); + if (draw_center && (!aa_on || blend_on || !draw_border)) { + draw_ring(verts, indices, colors, border_style_rect, adapted_corner, + infill_rect, infill_rect, bg_color, bg_color, corner_detail, true); } if (aa_on) { - Rect2 border_inner_rect = infill_rect; int aa_border_width[4]; int aa_fill_width[4]; if (draw_border) { - border_inner_rect = border_style_rect.grow_individual(-adapted_border[MARGIN_LEFT], -adapted_border[MARGIN_TOP], -adapted_border[MARGIN_RIGHT], -adapted_border[MARGIN_BOTTOM]); for (int i = 0; i < 4; i++) { if (border_width[i] > 0) { - aa_border_width[i] = aa_size; + aa_border_width[i] = aa_size_grow; aa_fill_width[i] = 0; } else { aa_border_width[i] = 0; - aa_fill_width[i] = aa_size; + aa_fill_width[i] = aa_size_grow; } } } else { for (int i = 0; i < 4; i++) { - aa_fill_width[i] = aa_size; + aa_border_width[i] = 0; + aa_fill_width[i] = aa_size_grow; } } + Rect2 infill_inner_rect = infill_rect.grow_individual(-aa_border_width[MARGIN_LEFT], -aa_border_width[MARGIN_TOP], + -aa_border_width[MARGIN_RIGHT], -aa_border_width[MARGIN_BOTTOM]); + if (draw_center) { - if (!draw_border || !blend_on) { - Rect2 aa_rect = infill_rect.grow_individual(aa_fill_width[MARGIN_LEFT], aa_fill_width[MARGIN_TOP], + if (!blend_on && draw_border) { + //DRAW INFILL WITHIN BORDER AA + draw_ring(verts, indices, colors, border_style_rect, adapted_corner, + infill_inner_rect, infill_inner_rect, bg_color, bg_color, corner_detail, true); + } + + if (!blend_on || !draw_border) { + Rect2 infill_aa_rect = infill_rect.grow_individual(aa_fill_width[MARGIN_LEFT], aa_fill_width[MARGIN_TOP], aa_fill_width[MARGIN_RIGHT], aa_fill_width[MARGIN_BOTTOM]); Color alpha_bg = Color(bg_color.r, bg_color.g, bg_color.b, 0); //INFILL AA draw_ring(verts, indices, colors, style_rect, adapted_corner, - aa_rect, aa_fill_width, bg_color, alpha_bg, corner_detail); + infill_aa_rect, infill_rect, bg_color, alpha_bg, corner_detail); } } @@ -811,20 +834,17 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const { if (!blend_on) { //DRAW INNER BORDER AA draw_ring(verts, indices, colors, border_style_rect, adapted_corner, - border_inner_rect, aa_border_width, border_color_alpha, border_color, corner_detail); + infill_rect, infill_inner_rect, border_color_blend, border_color, corner_detail); } - Rect2 aa_rect = border_style_rect.grow_individual(aa_border_width[MARGIN_LEFT], aa_border_width[MARGIN_TOP], - aa_border_width[MARGIN_RIGHT], aa_border_width[MARGIN_BOTTOM]); - //DRAW OUTER BORDER AA draw_ring(verts, indices, colors, border_style_rect, adapted_corner, - aa_rect, aa_border_width, border_color, border_color_alpha, corner_detail); + style_rect, border_style_rect, border_color, border_color_alpha, corner_detail); } } //COMPUTE UV COORDINATES - Rect2 uv_rect = style_rect.grow(aa_on ? aa_size : 0); + Rect2 uv_rect = style_rect.grow(aa_on ? aa_size_grow : 0); uvs.resize(verts.size()); for (int i = 0; i < verts.size(); i++) { uvs.write[i].x = (verts[i].x - uv_rect.position.x) / uv_rect.size.width; @@ -910,7 +930,7 @@ void StyleBoxFlat::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_bottom_right", PROPERTY_HINT_RANGE, "0,1024,1"), "set_corner_radius", "get_corner_radius", CORNER_BOTTOM_RIGHT); ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_bottom_left", PROPERTY_HINT_RANGE, "0,1024,1"), "set_corner_radius", "get_corner_radius", CORNER_BOTTOM_LEFT); - ADD_PROPERTY(PropertyInfo(Variant::INT, "corner_detail", PROPERTY_HINT_RANGE, "1,128,1"), "set_corner_detail", "get_corner_detail"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "corner_detail", PROPERTY_HINT_RANGE, "1,20,1"), "set_corner_detail", "get_corner_detail"); ADD_GROUP("Expand Margin", "expand_margin_"); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "expand_margin_left", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin", "get_expand_margin", MARGIN_LEFT); diff --git a/scene/resources/style_box.h b/scene/resources/style_box.h index d02e107480..3e0fffdcd9 100644 --- a/scene/resources/style_box.h +++ b/scene/resources/style_box.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -56,6 +56,7 @@ public: float get_margin(Margin p_margin) const; virtual Size2 get_center_size() const; + virtual Rect2 get_draw_rect(const Rect2 &p_rect) const; virtual void draw(RID p_canvas_item, const Rect2 &p_rect) const = 0; CanvasItem *get_current_item_drawn() const; @@ -133,6 +134,7 @@ public: void set_modulate(const Color &p_modulate); Color get_modulate() const; + virtual Rect2 get_draw_rect(const Rect2 &p_rect) const; virtual void draw(RID p_canvas_item, const Rect2 &p_rect) const; StyleBoxTexture(); @@ -227,6 +229,7 @@ public: virtual Size2 get_center_size() const; + virtual Rect2 get_draw_rect(const Rect2 &p_rect) const; virtual void draw(RID p_canvas_item, const Rect2 &p_rect) const; StyleBoxFlat(); diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index b294991248..f921a9695c 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h index e3aec6ce0e..89034f656d 100644 --- a/scene/resources/surface_tool.h +++ b/scene/resources/surface_tool.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/text_file.cpp b/scene/resources/text_file.cpp index 3faedc883d..af55d2dde3 100644 --- a/scene/resources/text_file.cpp +++ b/scene/resources/text_file.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/text_file.h b/scene/resources/text_file.h index 7127eaeb93..666c088d04 100644 --- a/scene/resources/text_file.h +++ b/scene/resources/text_file.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 593c399f62..b7805b7e38 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -1333,6 +1333,7 @@ void LargeTexture::set_piece_offset(int p_idx, const Point2 &p_offset) { void LargeTexture::set_piece_texture(int p_idx, const Ref<Texture> &p_texture) { ERR_FAIL_COND(p_texture == this); + ERR_FAIL_COND(p_texture.is_null()); ERR_FAIL_INDEX(p_idx, pieces.size()); pieces.write[p_idx].texture = p_texture; }; @@ -2270,6 +2271,7 @@ void TextureLayered::create(uint32_t p_width, uint32_t p_height, uint32_t p_dept void TextureLayered::set_layer_data(const Ref<Image> &p_image, int p_layer) { ERR_FAIL_COND(!texture.is_valid()); + ERR_FAIL_COND(!p_image.is_valid()); VS::get_singleton()->texture_set_data(texture, p_image, p_layer); } @@ -2281,6 +2283,7 @@ Ref<Image> TextureLayered::get_layer_data(int p_layer) const { void TextureLayered::set_data_partial(const Ref<Image> &p_image, int p_x_ofs, int p_y_ofs, int p_z, int p_mipmap) { ERR_FAIL_COND(!texture.is_valid()); + ERR_FAIL_COND(!p_image.is_valid()); VS::get_singleton()->texture_set_data_partial(texture, p_image, 0, 0, p_image->get_width(), p_image->get_height(), p_x_ofs, p_y_ofs, p_mipmap, p_z); } @@ -2371,13 +2374,13 @@ RES ResourceFormatLoaderTextureLayered::load(const String &p_path, const String if (tex3d.is_null()) { f->close(); memdelete(f); - ERR_FAIL_COND_V(tex3d.is_null(), RES()) + ERR_FAIL_COND_V(tex3d.is_null(), RES()); } } else if (header[0] == 'G' && header[1] == 'D' && header[2] == 'A' && header[3] == 'T') { if (texarr.is_null()) { f->close(); memdelete(f); - ERR_FAIL_COND_V(texarr.is_null(), RES()) + ERR_FAIL_COND_V(texarr.is_null(), RES()); } } else { diff --git a/scene/resources/texture.h b/scene/resources/texture.h index e535f7544a..fa698d387b 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -45,7 +45,8 @@ class Texture : public Resource { GDCLASS(Texture, Resource); - OBJ_SAVE_TYPE(Texture); //children are all saved as Texture, so they can be exchanged + OBJ_SAVE_TYPE(Texture); // Saves derived classes with common type so they can be interchanged. + protected: static void _bind_methods(); diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp index c897365b21..1f2fa1d60b 100644 --- a/scene/resources/theme.cpp +++ b/scene/resources/theme.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -720,7 +720,10 @@ void Theme::clear() { while ((K = icon_map.next(K))) { const StringName *L = NULL; while ((L = icon_map[*K].next(L))) { - icon_map[*K][*L]->disconnect("changed", this, "_emit_theme_changed"); + Ref<Texture> icon = icon_map[*K][*L]; + if (icon.is_valid()) { + icon->disconnect("changed", this, "_emit_theme_changed"); + } } } } @@ -730,7 +733,10 @@ void Theme::clear() { while ((K = style_map.next(K))) { const StringName *L = NULL; while ((L = style_map[*K].next(L))) { - style_map[*K][*L]->disconnect("changed", this, "_emit_theme_changed"); + Ref<StyleBox> style = style_map[*K][*L]; + if (style.is_valid()) { + style->disconnect("changed", this, "_emit_theme_changed"); + } } } } @@ -740,7 +746,10 @@ void Theme::clear() { while ((K = font_map.next(K))) { const StringName *L = NULL; while ((L = font_map[*K].next(L))) { - font_map[*K][*L]->disconnect("changed", this, "_emit_theme_changed"); + Ref<Font> font = font_map[*K][*L]; + if (font.is_valid()) { + font->disconnect("changed", this, "_emit_theme_changed"); + } } } } diff --git a/scene/resources/theme.h b/scene/resources/theme.h index 471e5b1a51..4bb614b24e 100644 --- a/scene/resources/theme.h +++ b/scene/resources/theme.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 16a95e65a8..db5037172e 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -325,14 +325,14 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { int id = E->key(); String pre = itos(id) + "/"; - p_list->push_back(PropertyInfo(Variant::STRING, pre + "name")); - p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture")); - p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture")); - p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "tex_offset")); - p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial")); - p_list->push_back(PropertyInfo(Variant::COLOR, pre + "modulate")); - p_list->push_back(PropertyInfo(Variant::RECT2, pre + "region")); - p_list->push_back(PropertyInfo(Variant::INT, pre + "tile_mode", PROPERTY_HINT_ENUM, "SINGLE_TILE,AUTO_TILE,ATLAS_TILE")); + p_list->push_back(PropertyInfo(Variant::STRING, pre + "name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "tex_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::COLOR, pre + "modulate", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::RECT2, pre + "region", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::INT, pre + "tile_mode", PROPERTY_HINT_ENUM, "SINGLE_TILE,AUTO_TILE,ATLAS_TILE", PROPERTY_USAGE_NOEDITOR)); if (tile_get_tile_mode(id) == AUTO_TILE) { p_list->push_back(PropertyInfo(Variant::INT, pre + "autotile/bitmask_mode", PROPERTY_HINT_ENUM, "2X2,3X3 (minimal),3X3", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/bitmask_flags", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); @@ -352,17 +352,17 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/priority_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/z_index_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); } - p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "occluder_offset")); - p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "occluder", PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D")); - p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "navigation_offset")); - p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "navigation", PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon")); - p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "shape_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "shape_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D", PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::BOOL, pre + "shape_one_way", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::REAL, pre + "shape_one_way_margin", PROPERTY_HINT_RANGE, "0,128,0.01", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "occluder_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "occluder", PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "navigation_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "navigation", PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "shape_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "shape_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::BOOL, pre + "shape_one_way", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::REAL, pre + "shape_one_way_margin", PROPERTY_HINT_RANGE, "0,128,0.01", PROPERTY_USAGE_NOEDITOR)); p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "shapes", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); - p_list->push_back(PropertyInfo(Variant::INT, pre + "z_index", PROPERTY_HINT_RANGE, itos(VS::CANVAS_ITEM_Z_MIN) + "," + itos(VS::CANVAS_ITEM_Z_MAX) + ",1")); + p_list->push_back(PropertyInfo(Variant::INT, pre + "z_index", PROPERTY_HINT_RANGE, itos(VS::CANVAS_ITEM_Z_MIN) + "," + itos(VS::CANVAS_ITEM_Z_MAX) + ",1", PROPERTY_USAGE_NOEDITOR)); } } @@ -1038,6 +1038,7 @@ void TileSet::_tile_set_shapes(int p_id, const Array &p_shapes) { } tile_map[p_id].shapes_data = shapes_data; + emit_changed(); } Array TileSet::_tile_get_shapes(int p_id) const { @@ -1232,6 +1233,7 @@ void TileSet::_bind_methods() { BIND_ENUM_CONSTANT(BIND_TOP); BIND_ENUM_CONSTANT(BIND_TOPRIGHT); BIND_ENUM_CONSTANT(BIND_LEFT); + BIND_ENUM_CONSTANT(BIND_CENTER); BIND_ENUM_CONSTANT(BIND_RIGHT); BIND_ENUM_CONSTANT(BIND_BOTTOMLEFT); BIND_ENUM_CONSTANT(BIND_BOTTOM); diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h index 5fc22b9fc6..eab40ce467 100644 --- a/scene/resources/tile_set.h +++ b/scene/resources/tile_set.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/video_stream.h b/scene/resources/video_stream.h index 81c7b062cc..444bb698ae 100644 --- a/scene/resources/video_stream.h +++ b/scene/resources/video_stream.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -37,9 +37,6 @@ class VideoStreamPlayback : public Resource { GDCLASS(VideoStreamPlayback, Resource); -protected: - static void _bind_methods(); - public: typedef int (*AudioMixCallback)(void *p_udata, const float *p_data, int p_frames); @@ -61,28 +58,22 @@ public: virtual void set_audio_track(int p_idx) = 0; - //virtual int mix(int16_t* p_buffer,int p_frames)=0; - virtual Ref<Texture> get_texture() const = 0; virtual void update(float p_delta) = 0; virtual void set_mix_callback(AudioMixCallback p_callback, void *p_userdata) = 0; virtual int get_channels() const = 0; virtual int get_mix_rate() const = 0; - - VideoStreamPlayback(); }; class VideoStream : public Resource { GDCLASS(VideoStream, Resource); - OBJ_SAVE_TYPE(VideoStream); //children are all saved as AudioStream, so they can be exchanged + OBJ_SAVE_TYPE(VideoStream); // Saves derived classes with common type so they can be interchanged. public: virtual void set_audio_track(int p_track) = 0; virtual Ref<VideoStreamPlayback> instance_playback() = 0; - - VideoStream() {} }; #endif diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index 9f99732714..b3a72ea7b6 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,6 +33,10 @@ #include "core/vmap.h" #include "servers/visual/shader_types.h" +bool VisualShaderNode::is_simple_decl() const { + return simple_decl; +} + void VisualShaderNode::set_output_port_for_preview(int p_index) { port_preview = p_index; @@ -79,7 +83,7 @@ Vector<StringName> VisualShaderNode::get_editable_properties() const { return Vector<StringName>(); } -Array VisualShaderNode::_get_default_input_values() const { +Array VisualShaderNode::get_default_input_values() const { Array ret; for (Map<int, Variant>::Element *E = default_input_values.front(); E; E = E->next()) { @@ -88,7 +92,7 @@ Array VisualShaderNode::_get_default_input_values() const { } return ret; } -void VisualShaderNode::_set_default_input_values(const Array &p_values) { +void VisualShaderNode::set_default_input_values(const Array &p_values) { if (p_values.size() % 2 == 0) { for (int i = 0; i < p_values.size(); i += 2) { @@ -115,11 +119,11 @@ void VisualShaderNode::_bind_methods() { ClassDB::bind_method(D_METHOD("set_input_port_default_value", "port", "value"), &VisualShaderNode::set_input_port_default_value); ClassDB::bind_method(D_METHOD("get_input_port_default_value", "port"), &VisualShaderNode::get_input_port_default_value); - ClassDB::bind_method(D_METHOD("_set_default_input_values", "values"), &VisualShaderNode::_set_default_input_values); - ClassDB::bind_method(D_METHOD("_get_default_input_values"), &VisualShaderNode::_get_default_input_values); + ClassDB::bind_method(D_METHOD("set_default_input_values", "values"), &VisualShaderNode::set_default_input_values); + ClassDB::bind_method(D_METHOD("get_default_input_values"), &VisualShaderNode::get_default_input_values); ADD_PROPERTY(PropertyInfo(Variant::INT, "output_port_for_preview"), "set_output_port_for_preview", "get_output_port_for_preview"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "default_input_values", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_default_input_values", "_get_default_input_values"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "default_input_values", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_default_input_values", "get_default_input_values"); ADD_SIGNAL(MethodInfo("editor_refresh_request")); BIND_ENUM_CONSTANT(PORT_TYPE_SCALAR); @@ -132,6 +136,7 @@ void VisualShaderNode::_bind_methods() { VisualShaderNode::VisualShaderNode() { port_preview = -1; + simple_decl = true; } ///////////////////////////////////////////////////////// @@ -241,6 +246,7 @@ String VisualShaderNodeCustom::generate_code(Shader::Mode p_mode, VisualShader:: code.remove(code.size() - 1); code += "}"; } + code += "\n"; return code; } @@ -273,6 +279,7 @@ void VisualShaderNodeCustom::_bind_methods() { } VisualShaderNodeCustom::VisualShaderNodeCustom() { + simple_decl = false; } ///////////////////////////////////////////////////////// @@ -378,6 +385,9 @@ void VisualShader::remove_node(Type p_type, int p_id) { List<Connection>::Element *N = E->next(); if (E->get().from_node == p_id || E->get().to_node == p_id) { g->connections.erase(E); + if (E->get().from_node == p_id) { + g->nodes[E->get().to_node].prev_connected_nodes.erase(p_id); + } } E = N; } @@ -399,6 +409,25 @@ bool VisualShader::is_node_connection(Type p_type, int p_from_node, int p_from_p return false; } +bool VisualShader::is_nodes_connected_relatively(const Graph *p_graph, int p_node, int p_target) const { + bool result = false; + + const VisualShader::Node &node = p_graph->nodes[p_node]; + + for (const List<int>::Element *E = node.prev_connected_nodes.front(); E; E = E->next()) { + + if (E->get() == p_target) { + return true; + } + + result = is_nodes_connected_relatively(p_graph, E->get(), p_target); + if (result) { + break; + } + } + return result; +} + bool VisualShader::can_connect_nodes(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) const { ERR_FAIL_INDEX_V(p_type, TYPE_MAX, false); @@ -433,6 +462,9 @@ bool VisualShader::can_connect_nodes(Type p_type, int p_from_node, int p_from_po } } + if (is_nodes_connected_relatively(g, p_from_node, p_to_node)) + return false; + return true; } @@ -449,6 +481,8 @@ void VisualShader::connect_nodes_forced(Type p_type, int p_from_node, int p_from c.to_node = p_to_node; c.to_port = p_to_port; g->connections.push_back(c); + g->nodes[p_to_node].prev_connected_nodes.push_back(p_from_node); + _queue_update(); } @@ -479,6 +513,7 @@ Error VisualShader::connect_nodes(Type p_type, int p_from_node, int p_from_port, c.to_node = p_to_node; c.to_port = p_to_port; g->connections.push_back(c); + g->nodes[p_to_node].prev_connected_nodes.push_back(p_from_node); _queue_update(); return OK; @@ -492,6 +527,7 @@ void VisualShader::disconnect_nodes(Type p_type, int p_from_node, int p_from_por if (E->get().from_node == p_from_node && E->get().from_port == p_from_port && E->get().to_node == p_to_node && E->get().to_port == p_to_port) { g->connections.erase(E); + g->nodes[p_to_node].prev_connected_nodes.erase(p_from_node); _queue_update(); return; } @@ -1075,17 +1111,17 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui } else if (in_type == out_type) { inputs[i] = src_var; } else if (in_type == VisualShaderNode::PORT_TYPE_SCALAR && out_type == VisualShaderNode::PORT_TYPE_VECTOR) { - inputs[i] = "dot(" + src_var + ",vec3(0.333333,0.333333,0.333333))"; + inputs[i] = "dot(" + src_var + ", vec3(0.333333, 0.333333, 0.333333))"; } else if (in_type == VisualShaderNode::PORT_TYPE_VECTOR && out_type == VisualShaderNode::PORT_TYPE_SCALAR) { inputs[i] = "vec3(" + src_var + ")"; } else if (in_type == VisualShaderNode::PORT_TYPE_BOOLEAN && out_type == VisualShaderNode::PORT_TYPE_VECTOR) { inputs[i] = "all(bvec3(" + src_var + "))"; } else if (in_type == VisualShaderNode::PORT_TYPE_BOOLEAN && out_type == VisualShaderNode::PORT_TYPE_SCALAR) { - inputs[i] = src_var + ">0.0?true:false"; + inputs[i] = src_var + " > 0.0 ? true : false"; } else if (in_type == VisualShaderNode::PORT_TYPE_SCALAR && out_type == VisualShaderNode::PORT_TYPE_BOOLEAN) { - inputs[i] = src_var + "?1.0:0.0"; + inputs[i] = src_var + " ? 1.0 : 0.0"; } else if (in_type == VisualShaderNode::PORT_TYPE_VECTOR && out_type == VisualShaderNode::PORT_TYPE_BOOLEAN) { - inputs[i] = "vec3(" + src_var + "?1.0:0.0)"; + inputs[i] = "vec3(" + src_var + " ? 1.0 : 0.0)"; } } else { @@ -1101,7 +1137,7 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui } else if (defval.get_type() == Variant::VECTOR3) { Vector3 val = defval; inputs[i] = "n_in" + itos(node) + "p" + itos(i); - code += "\tvec3 " + inputs[i] + " = " + vformat("vec3(%.5f,%.5f,%.5f);\n", val.x, val.y, val.z); + code += "\tvec3 " + inputs[i] + " = " + vformat("vec3(%.5f, %.5f, %.5f);\n", val.x, val.y, val.z); } else if (defval.get_type() == Variant::TRANSFORM) { Transform val = defval; val.basis.transpose(); @@ -1116,7 +1152,7 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui values.push_back(val.origin.y); values.push_back(val.origin.z); bool err = false; - code += "\tmat4 " + inputs[i] + " = " + String("mat4( vec4(%.5f,%.5f,%.5f,0.0),vec4(%.5f,%.5f,%.5f,0.0),vec4(%.5f,%.5f,%.5f,0.0),vec4(%.5f,%.5f,%.5f,1.0) );\n").sprintf(values, &err); + code += "\tmat4 " + inputs[i] + " = " + String("mat4(vec4(%.5f, %.5f, %.5f, 0.0), vec4(%.5f, %.5f, %.5f, 0.0), vec4(%.5f, %.5f, %.5f, 0.0), vec4(%.5f, %.5f, %.5f, 1.0));\n").sprintf(values, &err); } else { //will go empty, node is expected to know what it is doing at this point and handle it } @@ -1128,15 +1164,29 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui output_vars.resize(vsnode->get_output_port_count()); String *outputs = output_vars.ptrw(); - for (int i = 0; i < output_count; i++) { + if (vsnode->is_simple_decl()) { // less code to generate for some simple_decl nodes + for (int i = 0; i < output_count; i++) { + String var_name = "n_out" + itos(node) + "p" + itos(i); + switch (vsnode->get_output_port_type(i)) { + case VisualShaderNode::PORT_TYPE_SCALAR: outputs[i] = "float " + var_name; break; + case VisualShaderNode::PORT_TYPE_VECTOR: outputs[i] = "vec3 " + var_name; break; + case VisualShaderNode::PORT_TYPE_BOOLEAN: outputs[i] = "bool " + var_name; break; + case VisualShaderNode::PORT_TYPE_TRANSFORM: outputs[i] = "mat4 " + var_name; break; + default: { + } + } + } - outputs[i] = "n_out" + itos(node) + "p" + itos(i); - switch (vsnode->get_output_port_type(i)) { - case VisualShaderNode::PORT_TYPE_SCALAR: code += String() + "\tfloat " + outputs[i] + ";\n"; break; - case VisualShaderNode::PORT_TYPE_VECTOR: code += String() + "\tvec3 " + outputs[i] + ";\n"; break; - case VisualShaderNode::PORT_TYPE_BOOLEAN: code += String() + "\tbool " + outputs[i] + ";\n"; break; - case VisualShaderNode::PORT_TYPE_TRANSFORM: code += String() + "\tmat4 " + outputs[i] + ";\n"; break; - default: { + } else { + for (int i = 0; i < output_count; i++) { + outputs[i] = "n_out" + itos(node) + "p" + itos(i); + switch (vsnode->get_output_port_type(i)) { + case VisualShaderNode::PORT_TYPE_SCALAR: code += String() + "\tfloat " + outputs[i] + ";\n"; break; + case VisualShaderNode::PORT_TYPE_VECTOR: code += String() + "\tvec3 " + outputs[i] + ";\n"; break; + case VisualShaderNode::PORT_TYPE_BOOLEAN: code += String() + "\tbool " + outputs[i] + ";\n"; break; + case VisualShaderNode::PORT_TYPE_TRANSFORM: code += String() + "\tmat4 " + outputs[i] + ";\n"; break; + default: { + } } } } @@ -1326,6 +1376,7 @@ void VisualShader::_input_type_changed(Type p_type, int p_id) { List<Connection>::Element *N = E->next(); if (E->get().from_node == p_id) { g->connections.erase(E); + g->nodes[E->get().to_node].prev_connected_nodes.erase(p_id); } E = N; } @@ -1402,8 +1453,8 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "normal", "NORMAL" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "tangent", "TANGENT" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "binormal", "BINORMAL" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV,0.0)" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv2", "vec3(UV2,0.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv2", "vec3(UV2, 0.0)" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "point_size", "POINT_SIZE" }, @@ -1425,13 +1476,13 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "tangent", "TANGENT" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "binormal", "BINORMAL" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "view", "VIEW" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV,0.0)" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "uv2", "vec3(UV2,0.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "uv2", "vec3(UV2, 0.0)" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "point_coord", "vec3(POINT_COORD,0.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "point_coord", "vec3(POINT_COORD, 0.0)" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV,0.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "side", "float(FRONT_FACING ? 1.0 : 0.0)" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_TRANSFORM, "world", "WORLD_MATRIX" }, @@ -1468,7 +1519,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "viewport_size", "vec3(VIEWPORT_SIZE, 0.0)" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_BOOLEAN, "output_is_srgb", "OUTPUT_IS_SRGB" }, // Canvas Item, Vertex - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "vertex", "vec3(VERTEX,0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "vertex", "vec3(VERTEX, 0.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV,0.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, @@ -1482,13 +1533,13 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "light_pass", "float(AT_LIGHT_PASS ? 1.0 : 0.0)" }, // Canvas Item, Fragment { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "fragcoord", "FRAGCOORD.xyz" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV,0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV,0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "texture_pixel_size", "vec3(TEXTURE_PIXEL_SIZE, 1.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_pixel_size", "vec3(SCREEN_PIXEL_SIZE, 1.0)" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "point_coord", "vec3(POINT_COORD,0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "point_coord", "vec3(POINT_COORD, 0.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "light_pass", "float(AT_LIGHT_PASS ? 1.0 : 0.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "texture", "TEXTURE" }, @@ -1496,19 +1547,19 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "screen_texture", "SCREEN_TEXTURE" }, // Canvas Item, Light { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "fragcoord", "FRAGCOORD.xyz" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV,0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "normal", "NORMAL" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "light_vec", "vec3(LIGHT_VEC,0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "light_vec", "vec3(LIGHT_VEC, 0.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "light_height", "LIGHT_HEIGHT" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "light_color", "LIGHT_COLOR.rgb" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "light_alpha", "LIGHT_COLOR.a" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "light_uv", "vec3(LIGHT_UV,0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "light_uv", "vec3(LIGHT_UV, 0.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "shadow_color", "SHADOW_COLOR.rgb" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV,0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "texture_pixel_size", "vec3(TEXTURE_PIXEL_SIZE, 1.0)" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "point_coord", "vec3(POINT_COORD,0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "point_coord", "vec3(POINT_COORD, 0.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SAMPLER, "texture", "TEXTURE" }, @@ -1534,48 +1585,48 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { const VisualShaderNodeInput::Port VisualShaderNodeInput::preview_ports[] = { // Spatial, Fragment - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "normal", "vec3(0.0,0.0,1.0)" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "tangent", "vec3(0.0,1.0,0.0)" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "binormal", "vec3(1.0,0.0,0.0)" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV,0.0)" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "uv2", "vec3(UV,0.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "normal", "vec3(0.0, 0.0, 1.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "tangent", "vec3(0.0, 1.0, 0.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "binormal", "vec3(1.0, 0.0, 0.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "uv2", "vec3(UV, 0.0)" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "vec3(1.0)" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV,0.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "side", "1.0" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "viewport_size", "vec3(1.0,1.0, 0.0)" }, // Spatial, Light - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "normal", "vec3(0.0,0.0,1.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "normal", "vec3(0.0, 0.0, 1.0)" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "viewport_size", "vec3(1.0, 1.0, 0.0)" }, // Canvas Item, Vertex - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "vertex", "vec3(VERTEX,0.0)" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV,0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "vertex", "vec3(VERTEX, 0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "vec3(1.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, // Canvas Item, Fragment - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV,0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "vec3(1.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV,0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, // Canvas Item, Light - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV,0.0)" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "normal", "vec3(0.0,0.0,1.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "normal", "vec3(0.0, 0.0, 1.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "vec3(1.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV,0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, // Particles, Vertex { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "vec3(1.0)" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "vec3(0.0,0.0,1.0)" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "vec3(0.0, 0.0, 1.0)" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, { Shader::MODE_MAX, VisualShader::TYPE_MAX, VisualShaderNode::PORT_TYPE_TRANSFORM, NULL, NULL }, }; @@ -1860,7 +1911,7 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = { { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "normalmap_depth", "NORMALMAP_DEPTH" }, // Canvas Item, Light { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "light", "LIGHT.rgb" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "light_alpha", "LIGHT.rgb" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "light_alpha", "LIGHT.a" }, // Particles, Vertex { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, @@ -2259,6 +2310,8 @@ void VisualShaderNodeGroupBase::set_input_port_type(int p_id, int p_type) { int index = 0; for (int i = 0; i < inputs_strings.size(); i++) { Vector<String> arr = inputs_strings[i].split(","); + ERR_FAIL_COND(arr.size() != 3); + if (arr[0].to_int() == p_id) { index += arr[0].size(); count = arr[1].size() - 1; @@ -2292,6 +2345,8 @@ void VisualShaderNodeGroupBase::set_input_port_name(int p_id, const String &p_na int index = 0; for (int i = 0; i < inputs_strings.size(); i++) { Vector<String> arr = inputs_strings[i].split(","); + ERR_FAIL_COND(arr.size() != 3); + if (arr[0].to_int() == p_id) { index += arr[0].size() + arr[1].size(); count = arr[2].size() - 1; @@ -2325,6 +2380,8 @@ void VisualShaderNodeGroupBase::set_output_port_type(int p_id, int p_type) { int index = 0; for (int i = 0; i < output_strings.size(); i++) { Vector<String> arr = output_strings[i].split(","); + ERR_FAIL_COND(arr.size() != 3); + if (arr[0].to_int() == p_id) { index += arr[0].size(); count = arr[1].size() - 1; @@ -2358,6 +2415,8 @@ void VisualShaderNodeGroupBase::set_output_port_name(int p_id, const String &p_n int index = 0; for (int i = 0; i < output_strings.size(); i++) { Vector<String> arr = output_strings[i].split(","); + ERR_FAIL_COND(arr.size() != 3); + if (arr[0].to_int() == p_id) { index += arr[0].size() + arr[1].size(); count = arr[2].size() - 1; @@ -2405,6 +2464,8 @@ void VisualShaderNodeGroupBase::_apply_port_changes() { for (int i = 0; i < inputs_strings.size(); i++) { Vector<String> arr = inputs_strings[i].split(","); + ERR_FAIL_COND(arr.size() != 3); + Port port; port.type = (PortType)arr[1].to_int(); port.name = arr[2]; @@ -2412,6 +2473,8 @@ void VisualShaderNodeGroupBase::_apply_port_changes() { } for (int i = 0; i < outputs_strings.size(); i++) { Vector<String> arr = outputs_strings[i].split(","); + ERR_FAIL_COND(arr.size() != 3); + Port port; port.type = (PortType)arr[1].to_int(); port.name = arr[2]; @@ -2460,13 +2523,7 @@ void VisualShaderNodeGroupBase::_bind_methods() { ClassDB::bind_method(D_METHOD("get_free_input_port_id"), &VisualShaderNodeGroupBase::get_free_input_port_id); ClassDB::bind_method(D_METHOD("get_free_output_port_id"), &VisualShaderNodeGroupBase::get_free_output_port_id); - ClassDB::bind_method(D_METHOD("set_control", "control", "index"), &VisualShaderNodeGroupBase::set_control); - ClassDB::bind_method(D_METHOD("get_control", "index"), &VisualShaderNodeGroupBase::get_control); - - ClassDB::bind_method(D_METHOD("set_editable", "enabled"), &VisualShaderNodeGroupBase::set_editable); - ClassDB::bind_method(D_METHOD("is_editable"), &VisualShaderNodeGroupBase::is_editable); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editable"), "set_editable", "is_editable"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size"); } String VisualShaderNodeGroupBase::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { @@ -2478,6 +2535,7 @@ VisualShaderNodeGroupBase::VisualShaderNodeGroupBase() { inputs = ""; outputs = ""; editable = false; + simple_decl = false; } ////////////// Expression @@ -2490,10 +2548,6 @@ void VisualShaderNodeExpression::set_expression(const String &p_expression) { expression = p_expression; } -void VisualShaderNodeExpression::build() { - emit_changed(); -} - String VisualShaderNodeExpression::get_expression() const { return expression; } @@ -2583,14 +2637,14 @@ String VisualShaderNodeExpression::generate_code(Shader::Mode p_mode, VisualShad default: continue; } - output_initializer += "\t" + p_output_vars[i] + "=" + tk + ";\n"; + output_initializer += "\t" + p_output_vars[i] + " = " + tk + ";\n"; } String code; code += output_initializer; code += "\t{"; code += _expression; - code += "\n\t}"; + code += "\n\t}\n"; return code; } @@ -2600,8 +2654,6 @@ void VisualShaderNodeExpression::_bind_methods() { ClassDB::bind_method(D_METHOD("set_expression", "expression"), &VisualShaderNodeExpression::set_expression); ClassDB::bind_method(D_METHOD("get_expression"), &VisualShaderNodeExpression::get_expression); - ClassDB::bind_method(D_METHOD("build"), &VisualShaderNodeExpression::build); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "expression"), "set_expression", "get_expression"); } diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index 09222c8d81..f35318e090 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -65,6 +65,7 @@ private: struct Node { Ref<VisualShaderNode> node; Vector2 position; + List<int> prev_connected_nodes; }; struct Graph { @@ -135,6 +136,8 @@ public: void remove_node(Type p_type, int p_id); bool is_node_connection(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) const; + + bool is_nodes_connected_relatively(const Graph *p_graph, int p_node, int p_target) const; bool can_connect_nodes(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) const; Error connect_nodes(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port); void disconnect_nodes(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port); @@ -172,10 +175,8 @@ class VisualShaderNode : public Resource { Map<int, Variant> default_input_values; - Array _get_default_input_values() const; - void _set_default_input_values(const Array &p_values); - protected: + bool simple_decl; static void _bind_methods(); public: @@ -188,6 +189,8 @@ public: PORT_TYPE_MAX, }; + bool is_simple_decl() const; + virtual String get_caption() const = 0; virtual int get_input_port_count() const = 0; @@ -196,6 +199,8 @@ public: void set_input_port_default_value(int p_port, const Variant &p_value); Variant get_input_port_default_value(int p_port) const; // if NIL (default if node does not set anything) is returned, it means no default value is wanted if disconnected, thus no input var must be supplied (empty string will be supplied) + Array get_default_input_values() const; + void set_default_input_values(const Array &p_values); virtual int get_output_port_count() const = 0; virtual PortType get_output_port_type(int p_port) const = 0; @@ -455,8 +460,6 @@ public: void set_expression(const String &p_expression); String get_expression() const; - void build(); - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const; VisualShaderNodeExpression(); diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index a94fdd9d7b..8f0e0058ea 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -187,7 +187,7 @@ String VisualShaderNodeColorConstant::get_output_port_name(int p_port) const { String VisualShaderNodeColorConstant::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { String code; - code += "\t" + p_output_vars[0] + " = " + vformat("vec3(%.6f,%.6f,%.6f)", constant.r, constant.g, constant.b) + ";\n"; + code += "\t" + p_output_vars[0] + " = " + vformat("vec3(%.6f, %.6f, %.6f)", constant.r, constant.g, constant.b) + ";\n"; code += "\t" + p_output_vars[1] + " = " + vformat("%.6f", constant.a) + ";\n"; return code; @@ -253,7 +253,7 @@ String VisualShaderNodeVec3Constant::get_output_port_name(int p_port) const { } String VisualShaderNodeVec3Constant::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { - return "\t" + p_output_vars[0] + " = " + vformat("vec3(%.6f,%.6f,%.6f)", constant.x, constant.y, constant.z) + ";\n"; + return "\t" + p_output_vars[0] + " = " + vformat("vec3(%.6f, %.6f, %.6f)", constant.x, constant.y, constant.z) + ";\n"; } void VisualShaderNodeVec3Constant::set_constant(Vector3 p_value) { @@ -319,10 +319,10 @@ String VisualShaderNodeTransformConstant::generate_code(Shader::Mode p_mode, Vis t.basis.transpose(); String code = "\t" + p_output_vars[0] + " = mat4("; - code += vformat("vec4(%.6f,%.6f,%.6f,0.0),", t.basis[0].x, t.basis[0].y, t.basis[0].z); - code += vformat("vec4(%.6f,%.6f,%.6f,0.0),", t.basis[1].x, t.basis[1].y, t.basis[1].z); - code += vformat("vec4(%.6f,%.6f,%.6f,0.0),", t.basis[2].x, t.basis[2].y, t.basis[2].z); - code += vformat("vec4(%.6f,%.6f,%.6f,1.0) );\n", t.origin.x, t.origin.y, t.origin.z); + code += vformat("vec4(%.6f, %.6f, %.6f, 0.0), ", t.basis[0].x, t.basis[0].y, t.basis[0].z); + code += vformat("vec4(%.6f, %.6f, %.6f, 0.0), ", t.basis[1].x, t.basis[1].y, t.basis[1].z); + code += vformat("vec4(%.6f, %.6f, %.6f, 0.0), ", t.basis[2].x, t.basis[2].y, t.basis[2].z); + code += vformat("vec4(%.6f, %.6f, %.6f, 1.0));\n", t.origin.x, t.origin.y, t.origin.z); return code; } @@ -440,7 +440,7 @@ String VisualShaderNodeTexture::generate_global(Shader::Mode p_mode, VisualShade case TYPE_COLOR: u += " : hint_albedo"; break; case TYPE_NORMALMAP: u += " : hint_normal"; break; } - return u + ";"; + return u + ";\n"; } return String(); @@ -454,16 +454,16 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader: if (p_input_vars[0] == String()) { // Use UV by default. if (p_input_vars[1] == String()) { - code += "\tvec4 " + id + "_read = texture( " + id + " , UV.xy );\n"; + code += "\tvec4 " + id + "_read = texture(" + id + ", UV.xy);\n"; } else { - code += "\tvec4 " + id + "_read = textureLod( " + id + " , UV.xy , " + p_input_vars[1] + " );\n"; + code += "\tvec4 " + id + "_read = textureLod(" + id + ", UV.xy, " + p_input_vars[1] + ");\n"; } } else if (p_input_vars[1] == String()) { //no lod - code += "\tvec4 " + id + "_read = texture( " + id + " , " + p_input_vars[0] + ".xy );\n"; + code += "\tvec4 " + id + "_read = texture(" + id + ", " + p_input_vars[0] + ".xy);\n"; } else { - code += "\tvec4 " + id + "_read = textureLod( " + id + " , " + p_input_vars[0] + ".xy , " + p_input_vars[1] + " );\n"; + code += "\tvec4 " + id + "_read = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; } code += "\t" + p_output_vars[0] + " = " + id + "_read.rgb;\n"; @@ -482,16 +482,16 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader: if (p_input_vars[0] == String()) { // Use UV by default. if (p_input_vars[1] == String()) { - code += "\t\tvec4 " + id + "_tex_read = texture( " + id + " , UV.xy );\n"; + code += "\t\tvec4 " + id + "_tex_read = texture(" + id + ", UV.xy);\n"; } else { - code += "\t\tvec4 " + id + "_tex_read = textureLod( " + id + " , UV.xy , " + p_input_vars[1] + " );\n"; + code += "\t\tvec4 " + id + "_tex_read = textureLod(" + id + ", UV.xy, " + p_input_vars[1] + ");\n"; } } else if (p_input_vars[1] == String()) { //no lod - code += "\t\tvec4 " + id + "_tex_read = texture( " + id + " , " + p_input_vars[0] + ".xy );\n"; + code += "\t\tvec4 " + id + "_tex_read = texture(" + id + ", " + p_input_vars[0] + ".xy);\n"; } else { - code += "\t\tvec4 " + id + "_tex_read = textureLod( " + id + " , " + p_input_vars[0] + ".xy , " + p_input_vars[1] + " );\n"; + code += "\t\tvec4 " + id + "_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; } code += "\t\t" + p_output_vars[0] + " = " + id + "_tex_read.rgb;\n"; @@ -507,16 +507,16 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader: if (p_input_vars[0] == String() || p_for_preview) { // Use UV by default. if (p_input_vars[1] == String()) { - code += "\t\tvec4 _tex_read = textureLod( SCREEN_TEXTURE , UV.xy , 0.0 );\n"; + code += "\t\tvec4 _tex_read = textureLod(SCREEN_TEXTURE, UV.xy, 0.0 );\n"; } else { - code += "\t\tvec4 _tex_read = textureLod( SCREEN_TEXTURE , UV.xy , " + p_input_vars[1] + ");\n"; + code += "\t\tvec4 _tex_read = textureLod(SCREEN_TEXTURE, UV.xy, " + p_input_vars[1] + ");\n"; } } else if (p_input_vars[1] == String()) { //no lod - code += "\t\tvec4 _tex_read = textureLod( SCREEN_TEXTURE , " + p_input_vars[0] + ".xy , 0.0 );\n"; + code += "\t\tvec4 _tex_read = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ".xy, 0.0);\n"; } else { - code += "\t\tvec4 _tex_read = textureLod( SCREEN_TEXTURE , " + p_input_vars[0] + ".xy , " + p_input_vars[1] + " );\n"; + code += "\t\tvec4 _tex_read = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; } code += "\t\t" + p_output_vars[0] + " = _tex_read.rgb;\n"; @@ -531,16 +531,16 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader: if (p_input_vars[0] == String()) { // Use UV by default. if (p_input_vars[1] == String()) { - code += "\t\tvec4 _tex_read = texture( TEXTURE , UV.xy );\n"; + code += "\t\tvec4 _tex_read = texture(TEXTURE , UV.xy);\n"; } else { - code += "\t\tvec4 _tex_read = textureLod( TEXTURE , UV.xy , " + p_input_vars[1] + " );\n"; + code += "\t\tvec4 _tex_read = textureLod(TEXTURE, UV.xy, " + p_input_vars[1] + ");\n"; } } else if (p_input_vars[1] == String()) { //no lod - code += "\t\tvec4 _tex_read = texture( TEXTURE , " + p_input_vars[0] + ".xy );\n"; + code += "\t\tvec4 _tex_read = texture(TEXTURE, " + p_input_vars[0] + ".xy);\n"; } else { - code += "\t\tvec4 _tex_read = textureLod( TEXTURE , " + p_input_vars[0] + ".xy , " + p_input_vars[1] + " );\n"; + code += "\t\tvec4 _tex_read = textureLod(TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; } code += "\t\t" + p_output_vars[0] + " = _tex_read.rgb;\n"; @@ -555,16 +555,16 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader: if (p_input_vars[0] == String()) { // Use UV by default. if (p_input_vars[1] == String()) { - code += "\t\tvec4 _tex_read = texture( NORMAL_TEXTURE , UV.xy );\n"; + code += "\t\tvec4 _tex_read = texture(NORMAL_TEXTURE, UV.xy);\n"; } else { - code += "\t\tvec4 _tex_read = textureLod( NORMAL_TEXTURE , UV.xy , " + p_input_vars[1] + " );\n"; + code += "\t\tvec4 _tex_read = textureLod(NORMAL_TEXTURE, UV.xy, " + p_input_vars[1] + ");\n"; } } else if (p_input_vars[1] == String()) { //no lod - code += "\t\tvec4 _tex_read = texture( NORMAL_TEXTURE , " + p_input_vars[0] + ".xy );\n"; + code += "\t\tvec4 _tex_read = texture(NORMAL_TEXTURE, " + p_input_vars[0] + ".xy);\n"; } else { - code += "\t\tvec4 _tex_read = textureLod( NORMAL_TEXTURE , " + p_input_vars[0] + ".xy , " + p_input_vars[1] + " );\n"; + code += "\t\tvec4 _tex_read = textureLod(NORMAL_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; } code += "\t\t" + p_output_vars[0] + " = _tex_read.rgb;\n"; @@ -589,16 +589,16 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader: if (p_input_vars[0] == String()) { // Use UV by default. if (p_input_vars[1] == String()) { - code += "\t\tfloat _depth = texture( DEPTH_TEXTURE , UV.xy ).r;\n"; + code += "\t\tfloat _depth = texture(DEPTH_TEXTURE, UV.xy).r;\n"; } else { - code += "\t\tfloat _depth = textureLod( DEPTH_TEXTURE , UV.xy , " + p_input_vars[1] + " ).r;\n"; + code += "\t\tfloat _depth = textureLod(DEPTH_TEXTURE, UV.xy, " + p_input_vars[1] + ").r;\n"; } } else if (p_input_vars[1] == String()) { //no lod - code += "\t\tfloat _depth = texture( DEPTH_TEXTURE , " + p_input_vars[0] + ".xy ).r;\n"; + code += "\t\tfloat _depth = texture(DEPTH_TEXTURE, " + p_input_vars[0] + ".xy).r;\n"; } else { - code += "\t\tfloat _depth = textureLod( DEPTH_TEXTURE , " + p_input_vars[0] + ".xy , " + p_input_vars[1] + " ).r;\n"; + code += "\t\tfloat _depth = textureLod(DEPTH_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ").r;\n"; } code += "\t\t" + p_output_vars[0] + " = _depth;\n"; @@ -621,6 +621,26 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader: void VisualShaderNodeTexture::set_source(Source p_source) { source = p_source; + switch (source) { + case SOURCE_TEXTURE: + simple_decl = true; + break; + case SOURCE_SCREEN: + simple_decl = false; + break; + case SOURCE_2D_TEXTURE: + simple_decl = false; + break; + case SOURCE_2D_NORMAL: + simple_decl = false; + break; + case SOURCE_DEPTH: + simple_decl = false; + break; + case SOURCE_PORT: + simple_decl = false; + break; + } emit_changed(); emit_signal("editor_refresh_request"); } @@ -715,6 +735,7 @@ void VisualShaderNodeTexture::_bind_methods() { BIND_ENUM_CONSTANT(SOURCE_2D_TEXTURE); BIND_ENUM_CONSTANT(SOURCE_2D_NORMAL); BIND_ENUM_CONSTANT(SOURCE_DEPTH); + BIND_ENUM_CONSTANT(SOURCE_PORT); BIND_ENUM_CONSTANT(TYPE_DATA); BIND_ENUM_CONSTANT(TYPE_COLOR); BIND_ENUM_CONSTANT(TYPE_NORMALMAP); @@ -791,7 +812,7 @@ String VisualShaderNodeCubeMap::generate_global(Shader::Mode p_mode, VisualShade case TYPE_COLOR: u += " : hint_albedo"; break; case TYPE_NORMALMAP: u += " : hint_normal"; break; } - return u + ";"; + return u + ";\n"; } return String(); } @@ -808,29 +829,33 @@ String VisualShaderNodeCubeMap::generate_code(Shader::Mode p_mode, VisualShader: return String(); } + code += "\t{\n"; + if (id == String()) { - code += "\tvec4 " + id + "_read = vec4(0.0);\n"; - code += "\t" + p_output_vars[0] + " = " + id + "_read.rgb;\n"; - code += "\t" + p_output_vars[1] + " = " + id + "_read.a;\n"; + code += "\t\tvec4 " + id + "_read = vec4(0.0);\n"; + code += "\t\t" + p_output_vars[0] + " = " + id + "_read.rgb;\n"; + code += "\t\t" + p_output_vars[1] + " = " + id + "_read.a;\n"; + code += "\t}\n"; return code; } if (p_input_vars[0] == String()) { // Use UV by default. if (p_input_vars[1] == String()) { - code += "\tvec4 " + id + "_read = texture( " + id + " , vec3( UV, 0.0 ) );\n"; + code += "\t\tvec4 " + id + "_read = texture(" + id + " , vec3(UV, 0.0));\n"; } else { - code += "\tvec4 " + id + "_read = textureLod( " + id + " , vec3( UV, 0.0 )" + " , " + p_input_vars[1] + " );\n"; + code += "\t\tvec4 " + id + "_read = textureLod(" + id + " , vec3(UV, 0.0)" + " , " + p_input_vars[1] + " );\n"; } } else if (p_input_vars[1] == String()) { //no lod - code += "\tvec4 " + id + "_read = texture( " + id + " , " + p_input_vars[0] + " );\n"; + code += "\t\tvec4 " + id + "_read = texture(" + id + ", " + p_input_vars[0] + ");\n"; } else { - code += "\tvec4 " + id + "_read = textureLod( " + id + " , " + p_input_vars[0] + " , " + p_input_vars[1] + " );\n"; + code += "\t\tvec4 " + id + "_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } - code += "\t" + p_output_vars[0] + " = " + id + "_read.rgb;\n"; - code += "\t" + p_output_vars[1] + " = " + id + "_read.a;\n"; + code += "\t\t" + p_output_vars[0] + " = " + id + "_read.rgb;\n"; + code += "\t\t" + p_output_vars[1] + " = " + id + "_read.a;\n"; + code += "\t}\n"; return code; } @@ -908,6 +933,7 @@ void VisualShaderNodeCubeMap::_bind_methods() { VisualShaderNodeCubeMap::VisualShaderNodeCubeMap() { texture_type = TYPE_DATA; source = SOURCE_TEXTURE; + simple_decl = false; } ////////////// Scalar Op @@ -949,12 +975,12 @@ String VisualShaderNodeScalarOp::generate_code(Shader::Mode p_mode, VisualShader case OP_SUB: code += p_input_vars[0] + " - " + p_input_vars[1] + ";\n"; break; case OP_MUL: code += p_input_vars[0] + " * " + p_input_vars[1] + ";\n"; break; case OP_DIV: code += p_input_vars[0] + " / " + p_input_vars[1] + ";\n"; break; - case OP_MOD: code += "mod( " + p_input_vars[0] + " , " + p_input_vars[1] + " );\n"; break; - case OP_POW: code += "pow( " + p_input_vars[0] + " , " + p_input_vars[1] + " );\n"; break; - case OP_MAX: code += "max( " + p_input_vars[0] + " , " + p_input_vars[1] + " );\n"; break; - case OP_MIN: code += "min( " + p_input_vars[0] + " , " + p_input_vars[1] + " );\n"; break; - case OP_ATAN2: code += "atan( " + p_input_vars[0] + " , " + p_input_vars[1] + " );\n"; break; - case OP_STEP: code += "step( " + p_input_vars[0] + " , " + p_input_vars[1] + " );\n"; break; + case OP_MOD: code += "mod(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; + case OP_POW: code += "pow(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; + case OP_MAX: code += "max(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; + case OP_MIN: code += "min(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; + case OP_ATAN2: code += "atan(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; + case OP_STEP: code += "step(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; } return code; @@ -1041,14 +1067,14 @@ String VisualShaderNodeVectorOp::generate_code(Shader::Mode p_mode, VisualShader case OP_SUB: code += p_input_vars[0] + " - " + p_input_vars[1] + ";\n"; break; case OP_MUL: code += p_input_vars[0] + " * " + p_input_vars[1] + ";\n"; break; case OP_DIV: code += p_input_vars[0] + " / " + p_input_vars[1] + ";\n"; break; - case OP_MOD: code += "mod( " + p_input_vars[0] + " , " + p_input_vars[1] + " );\n"; break; - case OP_POW: code += "pow( " + p_input_vars[0] + " , " + p_input_vars[1] + " );\n"; break; - case OP_MAX: code += "max( " + p_input_vars[0] + " , " + p_input_vars[1] + " );\n"; break; - case OP_MIN: code += "min( " + p_input_vars[0] + " , " + p_input_vars[1] + " );\n"; break; - case OP_CROSS: code += "cross( " + p_input_vars[0] + " , " + p_input_vars[1] + " );\n"; break; - case OP_ATAN2: code += "atan( " + p_input_vars[0] + " , " + p_input_vars[1] + " );\n"; break; - case OP_REFLECT: code += "reflect( " + p_input_vars[0] + " , " + p_input_vars[1] + " );\n"; break; - case OP_STEP: code += "step( " + p_input_vars[0] + " , " + p_input_vars[1] + " );\n"; break; + case OP_MOD: code += "mod(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; + case OP_POW: code += "pow(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; + case OP_MAX: code += "max(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; + case OP_MIN: code += "min(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; + case OP_CROSS: code += "cross(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; + case OP_ATAN2: code += "atan(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; + case OP_REFLECT: code += "reflect(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; + case OP_STEP: code += "step(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; } return code; @@ -1135,27 +1161,27 @@ String VisualShaderNodeColorOp::generate_code(Shader::Mode p_mode, VisualShader: switch (op) { case OP_SCREEN: { - code += "\t" + p_output_vars[0] + "=vec3(1.0)-(vec3(1.0)-" + p_input_vars[0] + ")*(vec3(1.0)-" + p_input_vars[1] + ");\n"; + code += "\t" + p_output_vars[0] + " = vec3(1.0) - (vec3(1.0) - " + p_input_vars[0] + ") * (vec3(1.0) - " + p_input_vars[1] + ");\n"; } break; case OP_DIFFERENCE: { - code += "\t" + p_output_vars[0] + "=abs(" + p_input_vars[0] + "-" + p_input_vars[1] + ");\n"; + code += "\t" + p_output_vars[0] + " = abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ");\n"; } break; case OP_DARKEN: { - code += "\t" + p_output_vars[0] + "=min(" + p_input_vars[0] + "," + p_input_vars[1] + ");\n"; + code += "\t" + p_output_vars[0] + " = min(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } break; case OP_LIGHTEN: { - code += "\t" + p_output_vars[0] + "=max(" + p_input_vars[0] + "," + p_input_vars[1] + ");\n"; + code += "\t" + p_output_vars[0] + " = max(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } break; case OP_OVERLAY: { for (int i = 0; i < 3; i++) { code += "\t{\n"; - code += "\t\tfloat base=" + p_input_vars[0] + "." + axisn[i] + ";\n"; - code += "\t\tfloat blend=" + p_input_vars[1] + "." + axisn[i] + ";\n"; + code += "\t\tfloat base = " + p_input_vars[0] + "." + axisn[i] + ";\n"; + code += "\t\tfloat blend = " + p_input_vars[1] + "." + axisn[i] + ";\n"; code += "\t\tif (base < 0.5) {\n"; code += "\t\t\t" + p_output_vars[0] + "." + axisn[i] + " = 2.0 * base * blend;\n"; code += "\t\t} else {\n"; @@ -1167,23 +1193,23 @@ String VisualShaderNodeColorOp::generate_code(Shader::Mode p_mode, VisualShader: } break; case OP_DODGE: { - code += "\t" + p_output_vars[0] + "=(" + p_input_vars[0] + ")/(vec3(1.0)-" + p_input_vars[1] + ");\n"; + code += "\t" + p_output_vars[0] + " = (" + p_input_vars[0] + ") / (vec3(1.0) - " + p_input_vars[1] + ");\n"; } break; case OP_BURN: { - code += "\t" + p_output_vars[0] + "=vec3(1.0)-(vec3(1.0)-" + p_input_vars[0] + ")/(" + p_input_vars[1] + ");\n"; + code += "\t" + p_output_vars[0] + " = vec3(1.0) - (vec3(1.0) - " + p_input_vars[0] + ") / (" + p_input_vars[1] + ");\n"; } break; case OP_SOFT_LIGHT: { for (int i = 0; i < 3; i++) { code += "\t{\n"; - code += "\t\tfloat base=" + p_input_vars[0] + "." + axisn[i] + ";\n"; - code += "\t\tfloat blend=" + p_input_vars[1] + "." + axisn[i] + ";\n"; + code += "\t\tfloat base = " + p_input_vars[0] + "." + axisn[i] + ";\n"; + code += "\t\tfloat blend = " + p_input_vars[1] + "." + axisn[i] + ";\n"; code += "\t\tif (base < 0.5) {\n"; - code += "\t\t\t" + p_output_vars[0] + "." + axisn[i] + " = (base * (blend+0.5));\n"; + code += "\t\t\t" + p_output_vars[0] + "." + axisn[i] + " = (base * (blend + 0.5));\n"; code += "\t\t} else {\n"; - code += "\t\t\t" + p_output_vars[0] + "." + axisn[i] + " = (1.0 - (1.0-base) * (1.0-(blend-0.5)));\n"; + code += "\t\t\t" + p_output_vars[0] + "." + axisn[i] + " = (1.0 - (1.0 - base) * (1.0 - (blend - 0.5)));\n"; code += "\t\t}\n"; code += "\t}\n"; } @@ -1193,12 +1219,12 @@ String VisualShaderNodeColorOp::generate_code(Shader::Mode p_mode, VisualShader: for (int i = 0; i < 3; i++) { code += "\t{\n"; - code += "\t\tfloat base=" + p_input_vars[0] + "." + axisn[i] + ";\n"; - code += "\t\tfloat blend=" + p_input_vars[1] + "." + axisn[i] + ";\n"; + code += "\t\tfloat base = " + p_input_vars[0] + "." + axisn[i] + ";\n"; + code += "\t\tfloat blend = " + p_input_vars[1] + "." + axisn[i] + ";\n"; code += "\t\tif (base < 0.5) {\n"; - code += "\t\t\t" + p_output_vars[0] + "." + axisn[i] + " = (base * (2.0*blend));\n"; + code += "\t\t\t" + p_output_vars[0] + "." + axisn[i] + " = (base * (2.0 * blend));\n"; code += "\t\t} else {\n"; - code += "\t\t\t" + p_output_vars[0] + "." + axisn[i] + " = (1.0 - (1.0-base) * (1.0-2.0*(blend-0.5)));\n"; + code += "\t\t\t" + p_output_vars[0] + "." + axisn[i] + " = (1.0 - (1.0 - base) * (1.0 - 2.0 * (blend - 0.5)));\n"; code += "\t\t}\n"; code += "\t}\n"; } @@ -1212,6 +1238,35 @@ String VisualShaderNodeColorOp::generate_code(Shader::Mode p_mode, VisualShader: void VisualShaderNodeColorOp::set_operator(Operator p_op) { op = p_op; + switch (op) { + case OP_SCREEN: + simple_decl = true; + break; + case OP_DIFFERENCE: + simple_decl = true; + break; + case OP_DARKEN: + simple_decl = true; + break; + case OP_LIGHTEN: + simple_decl = true; + break; + case OP_OVERLAY: + simple_decl = false; + break; + case OP_DODGE: + simple_decl = true; + break; + case OP_BURN: + simple_decl = true; + break; + case OP_SOFT_LIGHT: + simple_decl = false; + break; + case OP_HARD_LIGHT: + simple_decl = false; + break; + } emit_changed(); } @@ -1287,9 +1342,9 @@ String VisualShaderNodeTransformMult::generate_code(Shader::Mode p_mode, VisualS } else if (op == OP_BxA) { return "\t" + p_output_vars[0] + " = " + p_input_vars[1] + " * " + p_input_vars[0] + ";\n"; } else if (op == OP_AxB_COMP) { - return "\t" + p_output_vars[0] + " = matrixCompMult( " + p_input_vars[0] + " , " + p_input_vars[1] + " );\n"; + return "\t" + p_output_vars[0] + " = matrixCompMult(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } else { - return "\t" + p_output_vars[0] + " = matrixCompMult( " + p_input_vars[1] + " , " + p_input_vars[0] + " );\n"; + return "\t" + p_output_vars[0] + " = matrixCompMult(" + p_input_vars[1] + ", " + p_input_vars[0] + ");\n"; } } @@ -1361,13 +1416,13 @@ String VisualShaderNodeTransformVecMult::get_output_port_name(int p_port) const String VisualShaderNodeTransformVecMult::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { if (op == OP_AxB) { - return "\t" + p_output_vars[0] + " = ( " + p_input_vars[0] + " * vec4(" + p_input_vars[1] + ", 1.0) ).xyz;\n"; + return "\t" + p_output_vars[0] + " = (" + p_input_vars[0] + " * vec4(" + p_input_vars[1] + ", 1.0)).xyz;\n"; } else if (op == OP_BxA) { - return "\t" + p_output_vars[0] + " = ( vec4(" + p_input_vars[1] + ", 1.0) * " + p_input_vars[0] + " ).xyz;\n"; + return "\t" + p_output_vars[0] + " = (vec4(" + p_input_vars[1] + ", 1.0) * " + p_input_vars[0] + ").xyz;\n"; } else if (op == OP_3x3_AxB) { - return "\t" + p_output_vars[0] + " = ( " + p_input_vars[0] + " * vec4(" + p_input_vars[1] + ", 0.0) ).xyz;\n"; + return "\t" + p_output_vars[0] + " = (" + p_input_vars[0] + " * vec4(" + p_input_vars[1] + ", 0.0)).xyz;\n"; } else { - return "\t" + p_output_vars[0] + " = ( vec4(" + p_input_vars[1] + ", 0.0) * " + p_input_vars[0] + " ).xyz;\n"; + return "\t" + p_output_vars[0] + " = (vec4(" + p_input_vars[1] + ", 0.0) * " + p_input_vars[0] + ").xyz;\n"; } } @@ -1458,7 +1513,7 @@ String VisualShaderNodeScalarFunc::generate_code(Shader::Mode p_mode, VisualShad "round($)", "ceil($)", "fract($)", - "min(max($,0.0),1.0)", + "min(max($, 0.0), 1.0)", "-($)", "acosh($)", "asinh($)", @@ -1468,10 +1523,10 @@ String VisualShaderNodeScalarFunc::generate_code(Shader::Mode p_mode, VisualShad "inversesqrt($)", "log2($)", "radians($)", - "1.0/($)", + "1.0 / ($)", "roundEven($)", "trunc($)", - "1.0-$" + "1.0 - $" }; return "\t" + p_output_vars[0] + " = " + String(scalar_func_id[func]).replace("$", p_input_vars[0]) + ";\n"; @@ -1574,9 +1629,9 @@ String VisualShaderNodeVectorFunc::generate_code(Shader::Mode p_mode, VisualShad static const char *vec_func_id[FUNC_ONEMINUS + 1] = { "normalize($)", - "max(min($,vec3(1.0)),vec3(0.0))", + "max(min($, vec3(1.0)), vec3(0.0))", "-($)", - "1.0/($)", + "1.0 / ($)", "", "", "abs($)", @@ -1607,7 +1662,7 @@ String VisualShaderNodeVectorFunc::generate_code(Shader::Mode p_mode, VisualShad "tan($)", "tanh($)", "trunc($)", - "vec3(1.0, 1.0, 1.0)-$" + "vec3(1.0, 1.0, 1.0) - $" }; String code; @@ -1620,18 +1675,18 @@ String VisualShaderNodeVectorFunc::generate_code(Shader::Mode p_mode, VisualShad code += "\t\tvec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n"; code += "\t\tfloat d = q.x - min(q.w, q.y);\n"; code += "\t\tfloat e = 1.0e-10;\n"; - code += "\t\t" + p_output_vars[0] + "=vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n"; + code += "\t\t" + p_output_vars[0] + " = vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n"; code += "\t}\n"; } else if (func == FUNC_HSV2RGB) { code += "\t{\n"; code += "\t\tvec3 c = " + p_input_vars[0] + ";\n"; code += "\t\tvec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n"; code += "\t\tvec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n"; - code += "\t\t" + p_output_vars[0] + "=c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n"; + code += "\t\t" + p_output_vars[0] + " = c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n"; code += "\t}\n"; } else { - code += "\t" + p_output_vars[0] + "=" + String(vec_func_id[func]).replace("$", p_input_vars[0]) + ";\n"; + code += "\t" + p_output_vars[0] + " = " + String(vec_func_id[func]).replace("$", p_input_vars[0]) + ";\n"; } return code; @@ -1640,6 +1695,13 @@ String VisualShaderNodeVectorFunc::generate_code(Shader::Mode p_mode, VisualShad void VisualShaderNodeVectorFunc::set_function(Function p_func) { func = p_func; + if (func == FUNC_RGB2HSV) { + simple_decl = false; + } else if (func == FUNC_HSV2RGB) { + simple_decl = false; + } else { + simple_decl = true; + } emit_changed(); } @@ -1792,6 +1854,7 @@ void VisualShaderNodeColorFunc::_bind_methods() { VisualShaderNodeColorFunc::VisualShaderNodeColorFunc() { func = FUNC_GRAYSCALE; set_input_port_default_value(0, Vector3()); + simple_decl = false; } ////////////// Transform Func @@ -1832,7 +1895,7 @@ String VisualShaderNodeTransformFunc::generate_code(Shader::Mode p_mode, VisualS }; String code; - code += "\t" + p_output_vars[0] + "=" + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n"; + code += "\t" + p_output_vars[0] + " = " + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n"; return code; } @@ -1900,7 +1963,7 @@ String VisualShaderNodeDotProduct::get_output_port_name(int p_port) const { } String VisualShaderNodeDotProduct::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { - return "\t" + p_output_vars[0] + " = dot( " + p_input_vars[0] + " , " + p_input_vars[1] + " );\n"; + return "\t" + p_output_vars[0] + " = dot(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } VisualShaderNodeDotProduct::VisualShaderNodeDotProduct() { @@ -1939,7 +2002,7 @@ String VisualShaderNodeVectorLen::get_output_port_name(int p_port) const { } String VisualShaderNodeVectorLen::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { - return "\t" + p_output_vars[0] + " = length( " + p_input_vars[0] + " );\n"; + return "\t" + p_output_vars[0] + " = length(" + p_input_vars[0] + ");\n"; } VisualShaderNodeVectorLen::VisualShaderNodeVectorLen() { @@ -1977,7 +2040,7 @@ String VisualShaderNodeDeterminant::get_output_port_name(int p_port) const { } String VisualShaderNodeDeterminant::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { - return "\t" + p_output_vars[0] + " = determinant( " + p_input_vars[0] + " );\n"; + return "\t" + p_output_vars[0] + " = determinant(" + p_input_vars[0] + ");\n"; } VisualShaderNodeDeterminant::VisualShaderNodeDeterminant() { @@ -2023,7 +2086,7 @@ String VisualShaderNodeScalarDerivativeFunc::generate_code(Shader::Mode p_mode, }; String code; - code += "\t" + p_output_vars[0] + "=" + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n"; + code += "\t" + p_output_vars[0] + " = " + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n"; return code; } @@ -2100,7 +2163,7 @@ String VisualShaderNodeVectorDerivativeFunc::generate_code(Shader::Mode p_mode, }; String code; - code += "\t" + p_output_vars[0] + "=" + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n"; + code += "\t" + p_output_vars[0] + " = " + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n"; return code; } @@ -2175,7 +2238,7 @@ String VisualShaderNodeScalarClamp::get_output_port_name(int p_port) const { } String VisualShaderNodeScalarClamp::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { - return "\t" + p_output_vars[0] + " = clamp( " + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + " );\n"; + return "\t" + p_output_vars[0] + " = clamp(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; } VisualShaderNodeScalarClamp::VisualShaderNodeScalarClamp() { @@ -2221,7 +2284,7 @@ String VisualShaderNodeVectorClamp::get_output_port_name(int p_port) const { } String VisualShaderNodeVectorClamp::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { - return "\t" + p_output_vars[0] + " = clamp( " + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + " );\n"; + return "\t" + p_output_vars[0] + " = clamp(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; } VisualShaderNodeVectorClamp::VisualShaderNodeVectorClamp() { @@ -2270,7 +2333,7 @@ String VisualShaderNodeFaceForward::get_output_port_name(int p_port) const { } String VisualShaderNodeFaceForward::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { - return "\t" + p_output_vars[0] + " = faceforward( " + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + " );\n"; + return "\t" + p_output_vars[0] + " = faceforward(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; } VisualShaderNodeFaceForward::VisualShaderNodeFaceForward() { @@ -2317,7 +2380,7 @@ String VisualShaderNodeOuterProduct::get_output_port_name(int p_port) const { } String VisualShaderNodeOuterProduct::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { - return "\t" + p_output_vars[0] + " = outerProduct( vec4(" + p_input_vars[0] + ", 0.0), vec4(" + p_input_vars[1] + ", 0.0) );\n"; + return "\t" + p_output_vars[0] + " = outerProduct(vec4(" + p_input_vars[0] + ", 0.0), vec4(" + p_input_vars[1] + ", 0.0));\n"; } VisualShaderNodeOuterProduct::VisualShaderNodeOuterProduct() { @@ -2363,7 +2426,7 @@ String VisualShaderNodeVectorScalarStep::get_output_port_name(int p_port) const } String VisualShaderNodeVectorScalarStep::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { - return "\t" + p_output_vars[0] + " = step( " + p_input_vars[0] + ", " + p_input_vars[1] + " );\n"; + return "\t" + p_output_vars[0] + " = step(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } VisualShaderNodeVectorScalarStep::VisualShaderNodeVectorScalarStep() { @@ -2408,7 +2471,7 @@ String VisualShaderNodeScalarSmoothStep::get_output_port_name(int p_port) const } String VisualShaderNodeScalarSmoothStep::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { - return "\t" + p_output_vars[0] + " = smoothstep( " + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + " );\n"; + return "\t" + p_output_vars[0] + " = smoothstep(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; } VisualShaderNodeScalarSmoothStep::VisualShaderNodeScalarSmoothStep() { @@ -2454,7 +2517,7 @@ String VisualShaderNodeVectorSmoothStep::get_output_port_name(int p_port) const } String VisualShaderNodeVectorSmoothStep::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { - return "\t" + p_output_vars[0] + " = smoothstep( " + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + " );\n"; + return "\t" + p_output_vars[0] + " = smoothstep(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; } VisualShaderNodeVectorSmoothStep::VisualShaderNodeVectorSmoothStep() { @@ -2505,7 +2568,7 @@ String VisualShaderNodeVectorScalarSmoothStep::get_output_port_name(int p_port) } String VisualShaderNodeVectorScalarSmoothStep::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { - return "\t" + p_output_vars[0] + " = smoothstep( " + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + " );\n"; + return "\t" + p_output_vars[0] + " = smoothstep(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; } VisualShaderNodeVectorScalarSmoothStep::VisualShaderNodeVectorScalarSmoothStep() { @@ -2550,7 +2613,7 @@ String VisualShaderNodeVectorDistance::get_output_port_name(int p_port) const { } String VisualShaderNodeVectorDistance::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { - return "\t" + p_output_vars[0] + " = distance( " + p_input_vars[0] + " , " + p_input_vars[1] + " );\n"; + return "\t" + p_output_vars[0] + " = distance(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } VisualShaderNodeVectorDistance::VisualShaderNodeVectorDistance() { @@ -2601,7 +2664,7 @@ String VisualShaderNodeVectorRefract::get_output_port_name(int p_port) const { } String VisualShaderNodeVectorRefract::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { - return "\t" + p_output_vars[0] + " = refract( " + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + " );\n"; + return "\t" + p_output_vars[0] + " = refract(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; } VisualShaderNodeVectorRefract::VisualShaderNodeVectorRefract() { @@ -2647,7 +2710,7 @@ String VisualShaderNodeScalarInterp::get_output_port_name(int p_port) const { } String VisualShaderNodeScalarInterp::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { - return "\t" + p_output_vars[0] + " = mix( " + p_input_vars[0] + " , " + p_input_vars[1] + " , " + p_input_vars[2] + " );\n"; + return "\t" + p_output_vars[0] + " = mix(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; } VisualShaderNodeScalarInterp::VisualShaderNodeScalarInterp() { @@ -2693,7 +2756,7 @@ String VisualShaderNodeVectorInterp::get_output_port_name(int p_port) const { } String VisualShaderNodeVectorInterp::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { - return "\t" + p_output_vars[0] + " = mix( " + p_input_vars[0] + " , " + p_input_vars[1] + " , " + p_input_vars[2] + " );\n"; + return "\t" + p_output_vars[0] + " = mix(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; } VisualShaderNodeVectorInterp::VisualShaderNodeVectorInterp() { @@ -2741,7 +2804,7 @@ String VisualShaderNodeVectorScalarMix::get_output_port_name(int p_port) const { } String VisualShaderNodeVectorScalarMix::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { - return "\t" + p_output_vars[0] + " = mix( " + p_input_vars[0] + " , " + p_input_vars[1] + " , " + p_input_vars[2] + " );\n"; + return "\t" + p_output_vars[0] + " = mix(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; } VisualShaderNodeVectorScalarMix::VisualShaderNodeVectorScalarMix() { @@ -2787,7 +2850,7 @@ String VisualShaderNodeVectorCompose::get_output_port_name(int p_port) const { } String VisualShaderNodeVectorCompose::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { - return "\t" + p_output_vars[0] + " = vec3( " + p_input_vars[0] + " , " + p_input_vars[1] + " , " + p_input_vars[2] + " );\n"; + return "\t" + p_output_vars[0] + " = vec3(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; } VisualShaderNodeVectorCompose::VisualShaderNodeVectorCompose() { @@ -2836,7 +2899,7 @@ String VisualShaderNodeTransformCompose::get_output_port_name(int p_port) const } String VisualShaderNodeTransformCompose::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { - return "\t" + p_output_vars[0] + " = mat4( vec4(" + p_input_vars[0] + ", 0.0) , vec4(" + p_input_vars[1] + ", 0.0) , vec4(" + p_input_vars[2] + ",0.0), vec4(" + p_input_vars[3] + ",1.0) );\n"; + return "\t" + p_output_vars[0] + " = mat4(vec4(" + p_input_vars[0] + ", 0.0), vec4(" + p_input_vars[1] + ", 0.0), vec4(" + p_input_vars[2] + ", 0.0), vec4(" + p_input_vars[3] + ", 1.0));\n"; } VisualShaderNodeTransformCompose::VisualShaderNodeTransformCompose() { @@ -2976,6 +3039,11 @@ String VisualShaderNodeScalarUniform::get_output_port_name(int p_port) const { } String VisualShaderNodeScalarUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + if (hint == HINT_RANGE) { + return "uniform float " + get_uniform_name() + " : hint_range(" + rtos(hint_range_min) + ", " + rtos(hint_range_max) + ");\n"; + } else if (hint == HINT_RANGE_STEP) { + return "uniform float " + get_uniform_name() + " : hint_range(" + rtos(hint_range_min) + ", " + rtos(hint_range_max) + ", " + rtos(hint_range_step) + ");\n"; + } return "uniform float " + get_uniform_name() + ";\n"; } @@ -2983,7 +3051,83 @@ String VisualShaderNodeScalarUniform::generate_code(Shader::Mode p_mode, VisualS return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; } +void VisualShaderNodeScalarUniform::set_hint(Hint p_hint) { + hint = p_hint; + emit_changed(); +} + +VisualShaderNodeScalarUniform::Hint VisualShaderNodeScalarUniform::get_hint() const { + return hint; +} + +void VisualShaderNodeScalarUniform::set_min(float p_value) { + hint_range_min = p_value; + emit_changed(); +} + +float VisualShaderNodeScalarUniform::get_min() const { + return hint_range_min; +} + +void VisualShaderNodeScalarUniform::set_max(float p_value) { + hint_range_max = p_value; + emit_changed(); +} + +float VisualShaderNodeScalarUniform::get_max() const { + return hint_range_max; +} + +void VisualShaderNodeScalarUniform::set_step(float p_value) { + hint_range_step = p_value; + emit_changed(); +} + +float VisualShaderNodeScalarUniform::get_step() const { + return hint_range_step; +} + +void VisualShaderNodeScalarUniform::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_hint", "hint"), &VisualShaderNodeScalarUniform::set_hint); + ClassDB::bind_method(D_METHOD("get_hint"), &VisualShaderNodeScalarUniform::get_hint); + + ClassDB::bind_method(D_METHOD("set_min", "value"), &VisualShaderNodeScalarUniform::set_min); + ClassDB::bind_method(D_METHOD("get_min"), &VisualShaderNodeScalarUniform::get_min); + + ClassDB::bind_method(D_METHOD("set_max", "value"), &VisualShaderNodeScalarUniform::set_max); + ClassDB::bind_method(D_METHOD("get_max"), &VisualShaderNodeScalarUniform::get_max); + + ClassDB::bind_method(D_METHOD("set_step", "value"), &VisualShaderNodeScalarUniform::set_step); + ClassDB::bind_method(D_METHOD("get_step"), &VisualShaderNodeScalarUniform::get_step); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "hint", PROPERTY_HINT_ENUM, "None,Range,Range+Step"), "set_hint", "get_hint"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "min"), "set_min", "get_min"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "max"), "set_max", "get_max"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "step"), "set_step", "get_step"); + + BIND_ENUM_CONSTANT(HINT_NONE); + BIND_ENUM_CONSTANT(HINT_RANGE); + BIND_ENUM_CONSTANT(HINT_RANGE_STEP); +} + +Vector<StringName> VisualShaderNodeScalarUniform::get_editable_properties() const { + Vector<StringName> props; + props.push_back("hint"); + if (hint == HINT_RANGE || hint == HINT_RANGE_STEP) { + props.push_back("min"); + props.push_back("max"); + } + if (hint == HINT_RANGE_STEP) { + props.push_back("step"); + } + return props; +} + VisualShaderNodeScalarUniform::VisualShaderNodeScalarUniform() { + hint = HINT_NONE; + hint_range_min = 0.0; + hint_range_max = 1.0; + hint_range_step = 0.1; } ////////////// Boolean Uniform @@ -3232,15 +3376,15 @@ String VisualShaderNodeTextureUniform::generate_code(Shader::Mode p_mode, Visual String code = "\t{\n"; if (p_input_vars[0] == String()) { // Use UV by default. if (p_input_vars[1] == String()) { - code += "\t\tvec4 n_tex_read = texture( " + id + " , UV.xy );\n"; + code += "\t\tvec4 n_tex_read = texture(" + id + ", UV.xy);\n"; } else { - code += "\t\tvec4 n_tex_read = textureLod( " + id + " , UV.xy , " + p_input_vars[1] + " );\n"; + code += "\t\tvec4 n_tex_read = textureLod(" + id + ", UV.xy, " + p_input_vars[1] + ");\n"; } } else if (p_input_vars[1] == String()) { //no lod - code += "\t\tvec4 n_tex_read = texture( " + id + " , " + p_input_vars[0] + ".xy );\n"; + code += "\t\tvec4 n_tex_read = texture(" + id + ", " + p_input_vars[0] + ".xy);\n"; } else { - code += "\t\tvec4 n_tex_read = textureLod( " + id + " , " + p_input_vars[0] + ".xy , " + p_input_vars[1] + " );\n"; + code += "\t\tvec4 n_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; } code += "\t\t" + p_output_vars[0] + " = n_tex_read.rgb;\n"; @@ -3304,6 +3448,7 @@ String VisualShaderNodeTextureUniform::get_input_port_default_hint(int p_port) c VisualShaderNodeTextureUniform::VisualShaderNodeTextureUniform() { texture_type = TYPE_DATA; color_default = COLOR_DEFAULT_WHITE; + simple_decl = false; } ////////////// Texture Uniform (Triplanar) @@ -3522,17 +3667,17 @@ String VisualShaderNodeIf::get_output_port_name(int p_port) const { String VisualShaderNodeIf::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { String code; - code += "\tif(abs(" + p_input_vars[0] + "-" + p_input_vars[1] + ")<" + p_input_vars[2] + ")\n"; // abs(a - b) < tolerance eg. a == b + code += "\tif(abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ") < " + p_input_vars[2] + ")\n"; // abs(a - b) < tolerance eg. a == b code += "\t{\n"; - code += "\t\t" + p_output_vars[0] + "=" + p_input_vars[3] + ";\n"; + code += "\t\t" + p_output_vars[0] + " = " + p_input_vars[3] + ";\n"; code += "\t}\n"; - code += "\telse if(" + p_input_vars[0] + "<" + p_input_vars[1] + ")\n"; // a < b + code += "\telse if(" + p_input_vars[0] + " < " + p_input_vars[1] + ")\n"; // a < b code += "\t{\n"; - code += "\t\t" + p_output_vars[0] + "=" + p_input_vars[5] + ";\n"; + code += "\t\t" + p_output_vars[0] + " = " + p_input_vars[5] + ";\n"; code += "\t}\n"; code += "\telse\n"; // a > b (or a >= b if abs(a - b) < tolerance is false) code += "\t{\n"; - code += "\t\t" + p_output_vars[0] + "=" + p_input_vars[4] + ";\n"; + code += "\t\t" + p_output_vars[0] + " = " + p_input_vars[4] + ";\n"; code += "\t}\n"; return code; } @@ -3544,6 +3689,7 @@ VisualShaderNodeIf::VisualShaderNodeIf() { set_input_port_default_value(3, Vector3(0.0, 0.0, 0.0)); set_input_port_default_value(4, Vector3(0.0, 0.0, 0.0)); set_input_port_default_value(5, Vector3(0.0, 0.0, 0.0)); + simple_decl = false; } ////////////// Switch @@ -3593,11 +3739,11 @@ String VisualShaderNodeSwitch::generate_code(Shader::Mode p_mode, VisualShader:: String code; code += "\tif(" + p_input_vars[0] + ")\n"; code += "\t{\n"; - code += "\t\t" + p_output_vars[0] + "=" + p_input_vars[1] + ";\n"; + code += "\t\t" + p_output_vars[0] + " = " + p_input_vars[1] + ";\n"; code += "\t}\n"; code += "\telse\n"; code += "\t{\n"; - code += "\t\t" + p_output_vars[0] + "=" + p_input_vars[2] + ";\n"; + code += "\t\t" + p_output_vars[0] + " = " + p_input_vars[2] + ";\n"; code += "\t}\n"; return code; } @@ -3606,6 +3752,7 @@ VisualShaderNodeSwitch::VisualShaderNodeSwitch() { set_input_port_default_value(0, false); set_input_port_default_value(1, Vector3(1.0, 1.0, 1.0)); set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0)); + simple_decl = false; } ////////////// Switch(scalar) @@ -3684,12 +3831,33 @@ String VisualShaderNodeFresnel::get_output_port_name(int p_port) const { } String VisualShaderNodeFresnel::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { - return "\t" + p_output_vars[0] + " = " + p_input_vars[2] + " ? (pow(clamp(dot(" + p_input_vars[0] + ", " + p_input_vars[1] + "), 0.0, 1.0), " + p_input_vars[3] + ")) : (pow(1.0 - clamp(dot(" + p_input_vars[0] + ", " + p_input_vars[1] + "), 0.0, 1.0), " + p_input_vars[3] + "));"; + + String normal; + String view; + if (p_input_vars[0] == String()) { + normal = "NORMAL"; + } else { + normal = p_input_vars[0]; + } + if (p_input_vars[1] == String()) { + view = "VIEW"; + } else { + view = p_input_vars[1]; + } + + return "\t" + p_output_vars[0] + " = " + p_input_vars[2] + " ? (pow(clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + ")) : (pow(1.0 - clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + "));\n"; +} + +String VisualShaderNodeFresnel::get_input_port_default_hint(int p_port) const { + if (p_port == 0) { + return "default"; + } else if (p_port == 1) { + return "default"; + } + return ""; } VisualShaderNodeFresnel::VisualShaderNodeFresnel() { - set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); - set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); set_input_port_default_value(2, false); set_input_port_default_value(3, 1.0); } @@ -3739,7 +3907,7 @@ String VisualShaderNodeIs::generate_code(Shader::Mode p_mode, VisualShader::Type }; String code; - code += "\t" + p_output_vars[0] + "=" + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n"; + code += "\t" + p_output_vars[0] + " = " + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n"; return code; } @@ -3874,31 +4042,31 @@ String VisualShaderNodeCompare::generate_code(Shader::Mode p_mode, VisualShader: switch (ctype) { case CTYPE_SCALAR: if (func == FUNC_EQUAL) { - code += "\t" + p_output_vars[0] + "=(abs(" + p_input_vars[0] + "-" + p_input_vars[1] + ")<" + p_input_vars[2] + ");"; + code += "\t" + p_output_vars[0] + " = (abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ") < " + p_input_vars[2] + ");"; } else if (func == FUNC_NOT_EQUAL) { - code += "\t" + p_output_vars[0] + "=!(abs(" + p_input_vars[0] + "-" + p_input_vars[1] + ")<" + p_input_vars[2] + ");"; + code += "\t" + p_output_vars[0] + " = !(abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ") < " + p_input_vars[2] + ");"; } else { - code += "\t" + p_output_vars[0] + "=" + (p_input_vars[0] + "$" + p_input_vars[1]).replace("$", ops[func]) + ";\n"; + code += "\t" + p_output_vars[0] + " = " + (p_input_vars[0] + "$" + p_input_vars[1]).replace("$", ops[func]) + ";\n"; } break; case CTYPE_VECTOR: code += "\t{\n"; - code += "\t\tbvec3 _bv=" + String(funcs[func]).replace("$", p_input_vars[0] + ", " + p_input_vars[1]) + ";\n"; - code += "\t\t" + p_output_vars[0] + "=" + String(conds[condition]).replace("$", "_bv") + ";\n"; + code += "\t\tbvec3 _bv = " + String(funcs[func]).replace("$", p_input_vars[0] + ", " + p_input_vars[1]) + ";\n"; + code += "\t\t" + p_output_vars[0] + " = " + String(conds[condition]).replace("$", "_bv") + ";\n"; code += "\t}\n"; break; case CTYPE_BOOLEAN: if (func > FUNC_NOT_EQUAL) - return "\t" + p_output_vars[0] + "=false;\n"; - code += "\t" + p_output_vars[0] + "=" + (p_input_vars[0] + "$" + p_input_vars[1]).replace("$", ops[func]) + ";\n"; + return "\t" + p_output_vars[0] + " = false;\n"; + code += "\t" + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", ops[func]) + ";\n"; break; case CTYPE_TRANSFORM: if (func > FUNC_NOT_EQUAL) - return "\t" + p_output_vars[0] + "=false;\n"; - code += "\t" + p_output_vars[0] + "=" + (p_input_vars[0] + "$" + p_input_vars[1]).replace("$", ops[func]) + ";\n"; + return "\t" + p_output_vars[0] + " = false;\n"; + code += "\t" + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", ops[func]) + ";\n"; break; default: @@ -3907,7 +4075,7 @@ String VisualShaderNodeCompare::generate_code(Shader::Mode p_mode, VisualShader: return code; } -void VisualShaderNodeCompare::set_comparsion_type(ComparsionType p_type) { +void VisualShaderNodeCompare::set_comparison_type(ComparisonType p_type) { ctype = p_type; @@ -3915,24 +4083,28 @@ void VisualShaderNodeCompare::set_comparsion_type(ComparsionType p_type) { case CTYPE_SCALAR: set_input_port_default_value(0, 0.0); set_input_port_default_value(1, 0.0); + simple_decl = true; break; case CTYPE_VECTOR: set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); + simple_decl = false; break; case CTYPE_BOOLEAN: set_input_port_default_value(0, false); set_input_port_default_value(1, false); + simple_decl = true; break; case CTYPE_TRANSFORM: set_input_port_default_value(0, Transform()); set_input_port_default_value(1, Transform()); + simple_decl = true; break; } emit_changed(); } -VisualShaderNodeCompare::ComparsionType VisualShaderNodeCompare::get_comparsion_type() const { +VisualShaderNodeCompare::ComparisonType VisualShaderNodeCompare::get_comparison_type() const { return ctype; } @@ -3970,8 +4142,8 @@ Vector<StringName> VisualShaderNodeCompare::get_editable_properties() const { void VisualShaderNodeCompare::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_comparsion_type", "type"), &VisualShaderNodeCompare::set_comparsion_type); - ClassDB::bind_method(D_METHOD("get_comparsion_type"), &VisualShaderNodeCompare::get_comparsion_type); + ClassDB::bind_method(D_METHOD("set_comparison_type", "type"), &VisualShaderNodeCompare::set_comparison_type); + ClassDB::bind_method(D_METHOD("get_comparison_type"), &VisualShaderNodeCompare::get_comparison_type); ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeCompare::set_function); ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeCompare::get_function); @@ -3979,7 +4151,7 @@ void VisualShaderNodeCompare::_bind_methods() { ClassDB::bind_method(D_METHOD("set_condition", "condition"), &VisualShaderNodeCompare::set_condition); ClassDB::bind_method(D_METHOD("get_condition"), &VisualShaderNodeCompare::get_condition); - ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, "Scalar,Vector,Boolean,Transform"), "set_comparsion_type", "get_comparsion_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, "Scalar,Vector,Boolean,Transform"), "set_comparison_type", "get_comparison_type"); ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "a == b,a != b,a > b,a >= b,a < b,a <= b"), "set_function", "get_function"); ADD_PROPERTY(PropertyInfo(Variant::INT, "condition", PROPERTY_HINT_ENUM, "All,Any"), "set_condition", "get_condition"); diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index 339e59bda9..3d57fd0efc 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -1301,6 +1301,22 @@ class VisualShaderNodeScalarUniform : public VisualShaderNodeUniform { GDCLASS(VisualShaderNodeScalarUniform, VisualShaderNodeUniform); public: + enum Hint { + HINT_NONE, + HINT_RANGE, + HINT_RANGE_STEP, + }; + +private: + Hint hint; + float hint_range_min; + float hint_range_max; + float hint_range_step; + +protected: + static void _bind_methods(); + +public: virtual String get_caption() const; virtual int get_input_port_count() const; @@ -1314,9 +1330,25 @@ public: virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + void set_hint(Hint p_hint); + Hint get_hint() const; + + void set_min(float p_value); + float get_min() const; + + void set_max(float p_value); + float get_max() const; + + void set_step(float p_value); + float get_step() const; + + virtual Vector<StringName> get_editable_properties() const; + VisualShaderNodeScalarUniform(); }; +VARIANT_ENUM_CAST(VisualShaderNodeScalarUniform::Hint) + /////////////////////////////////////// class VisualShaderNodeBooleanUniform : public VisualShaderNodeUniform { @@ -1579,6 +1611,7 @@ public: virtual PortType get_output_port_type(int p_port) const; virtual String get_output_port_name(int p_port) const; + virtual String get_input_port_default_hint(int p_port) const; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const; VisualShaderNodeFresnel(); @@ -1634,7 +1667,7 @@ class VisualShaderNodeCompare : public VisualShaderNode { GDCLASS(VisualShaderNodeCompare, VisualShaderNode); public: - enum ComparsionType { + enum ComparisonType { CTYPE_SCALAR, CTYPE_VECTOR, CTYPE_BOOLEAN, @@ -1656,7 +1689,7 @@ public: }; protected: - ComparsionType ctype; + ComparisonType ctype; Function func; Condition condition; @@ -1676,8 +1709,8 @@ public: virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty - void set_comparsion_type(ComparsionType p_type); - ComparsionType get_comparsion_type() const; + void set_comparison_type(ComparisonType p_type); + ComparisonType get_comparison_type() const; void set_function(Function p_func); Function get_function() const; @@ -1691,7 +1724,7 @@ public: VisualShaderNodeCompare(); }; -VARIANT_ENUM_CAST(VisualShaderNodeCompare::ComparsionType) +VARIANT_ENUM_CAST(VisualShaderNodeCompare::ComparisonType) VARIANT_ENUM_CAST(VisualShaderNodeCompare::Function) VARIANT_ENUM_CAST(VisualShaderNodeCompare::Condition) diff --git a/scene/resources/world.cpp b/scene/resources/world.cpp index 2c22f45f9d..e1e3974016 100644 --- a/scene/resources/world.cpp +++ b/scene/resources/world.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -262,18 +262,24 @@ RID World::get_space() const { return space; } + RID World::get_scenario() const { return scenario; } void World::set_environment(const Ref<Environment> &p_environment) { + if (environment == p_environment) { + return; + } environment = p_environment; if (environment.is_valid()) VS::get_singleton()->scenario_set_environment(scenario, environment->get_rid()); else VS::get_singleton()->scenario_set_environment(scenario, RID()); + + emit_changed(); } Ref<Environment> World::get_environment() const { @@ -282,12 +288,17 @@ Ref<Environment> World::get_environment() const { } void World::set_fallback_environment(const Ref<Environment> &p_environment) { + if (fallback_environment == p_environment) { + return; + } fallback_environment = p_environment; if (fallback_environment.is_valid()) VS::get_singleton()->scenario_set_fallback_environment(scenario, p_environment->get_rid()); else VS::get_singleton()->scenario_set_fallback_environment(scenario, RID()); + + emit_changed(); } Ref<Environment> World::get_fallback_environment() const { diff --git a/scene/resources/world.h b/scene/resources/world.h index 05d5ceb411..b6248b28c8 100644 --- a/scene/resources/world.h +++ b/scene/resources/world.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp index b5743ad416..5cc809d8e3 100644 --- a/scene/resources/world_2d.cpp +++ b/scene/resources/world_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/world_2d.h b/scene/resources/world_2d.h index e0c671e1a7..d837ef58c2 100644 --- a/scene/resources/world_2d.h +++ b/scene/resources/world_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp index 634f4d7160..6299c3a801 100644 --- a/scene/scene_string_names.cpp +++ b/scene/scene_string_names.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h index bc75165b8c..eeeaf22b01 100644 --- a/scene/scene_string_names.h +++ b/scene/scene_string_names.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ |