summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/animated_sprite.cpp6
-rw-r--r--scene/2d/area_2d.cpp7
-rw-r--r--scene/2d/canvas_item.cpp29
-rw-r--r--scene/2d/canvas_item.h2
-rw-r--r--scene/2d/collision_object_2d.cpp33
-rw-r--r--scene/2d/collision_object_2d.h3
-rw-r--r--scene/2d/collision_shape_2d.cpp4
-rw-r--r--scene/2d/light_2d.cpp4
-rw-r--r--scene/2d/line_2d.cpp8
-rw-r--r--scene/2d/node_2d.cpp17
-rw-r--r--scene/2d/node_2d.h3
-rw-r--r--scene/2d/physics_body_2d.cpp5
-rw-r--r--scene/2d/polygon_2d.cpp4
-rw-r--r--scene/2d/remote_transform_2d.cpp101
-rw-r--r--scene/2d/remote_transform_2d.h17
-rw-r--r--scene/2d/screen_button.cpp16
-rw-r--r--scene/2d/sprite.cpp13
-rw-r--r--scene/2d/tile_map.cpp8
-rw-r--r--scene/3d/area.cpp129
-rw-r--r--scene/3d/area.h28
-rw-r--r--scene/3d/arvr_nodes.cpp313
-rw-r--r--scene/3d/arvr_nodes.h126
-rw-r--r--scene/3d/audio_stream_player_3d.cpp930
-rw-r--r--scene/3d/audio_stream_player_3d.h175
-rw-r--r--scene/3d/body_shape.cpp920
-rw-r--r--scene/3d/camera.cpp40
-rw-r--r--scene/3d/camera.h16
-rw-r--r--scene/3d/collision_object.cpp313
-rw-r--r--scene/3d/collision_object.h58
-rw-r--r--scene/3d/collision_polygon.cpp237
-rw-r--r--scene/3d/collision_polygon.h29
-rw-r--r--scene/3d/collision_shape.cpp214
-rw-r--r--scene/3d/collision_shape.h (renamed from scene/3d/body_shape.h)38
-rw-r--r--scene/3d/gi_probe.cpp46
-rw-r--r--scene/3d/gi_probe.h11
-rw-r--r--scene/3d/light.cpp2
-rw-r--r--scene/3d/mesh_instance.cpp108
-rw-r--r--scene/3d/mesh_instance.h2
-rw-r--r--scene/3d/multimesh_instance.cpp4
-rw-r--r--scene/3d/navigation_mesh.cpp8
-rw-r--r--scene/3d/physics_body.cpp573
-rw-r--r--scene/3d/physics_body.h107
-rw-r--r--scene/3d/portal.cpp2
-rw-r--r--scene/3d/reflection_probe.cpp2
-rw-r--r--scene/3d/remote_transform.cpp96
-rw-r--r--scene/3d/remote_transform.h17
-rw-r--r--scene/3d/room_instance.cpp2
-rw-r--r--scene/3d/skeleton.cpp2
-rw-r--r--scene/3d/spatial.cpp30
-rw-r--r--scene/3d/spatial.h3
-rw-r--r--scene/3d/spatial_velocity_tracker.cpp104
-rw-r--r--scene/3d/spatial_velocity_tracker.h31
-rw-r--r--scene/audio/audio_player.cpp2
-rw-r--r--scene/gui/base_button.cpp8
-rw-r--r--scene/gui/button.cpp9
-rw-r--r--scene/gui/color_picker.cpp46
-rw-r--r--scene/gui/color_picker.h2
-rw-r--r--scene/gui/container.cpp18
-rw-r--r--scene/gui/control.cpp114
-rw-r--r--scene/gui/control.h24
-rw-r--r--scene/gui/dialogs.cpp6
-rw-r--r--scene/gui/gradient_edit.cpp4
-rw-r--r--scene/gui/graph_edit.cpp24
-rw-r--r--scene/gui/graph_edit.h2
-rw-r--r--scene/gui/item_list.cpp88
-rw-r--r--scene/gui/item_list.h11
-rw-r--r--scene/gui/label.cpp24
-rw-r--r--scene/gui/line_edit.cpp27
-rw-r--r--scene/gui/option_button.cpp21
-rw-r--r--scene/gui/patch_9_rect.cpp4
-rw-r--r--scene/gui/popup_menu.cpp25
-rw-r--r--scene/gui/popup_menu.h1
-rw-r--r--scene/gui/range.cpp6
-rw-r--r--scene/gui/rich_text_label.cpp35
-rw-r--r--scene/gui/rich_text_label.h6
-rw-r--r--scene/gui/slider.cpp29
-rw-r--r--scene/gui/slider.h4
-rw-r--r--scene/gui/spin_box.cpp2
-rw-r--r--scene/gui/split_container.cpp22
-rw-r--r--scene/gui/tabs.cpp71
-rw-r--r--scene/gui/tabs.h15
-rw-r--r--scene/gui/text_edit.cpp13
-rw-r--r--scene/gui/texture_button.cpp2
-rw-r--r--scene/gui/texture_progress.cpp12
-rw-r--r--scene/gui/texture_rect.cpp4
-rw-r--r--scene/gui/tree.cpp54
-rw-r--r--scene/gui/tree.h9
-rw-r--r--scene/io/resource_format_image.cpp4
-rwxr-xr-xscene/main/node.cpp113
-rw-r--r--scene/main/node.h21
-rw-r--r--scene/main/resource_preloader.cpp4
-rw-r--r--scene/main/scene_tree.cpp70
-rw-r--r--scene/main/scene_tree.h4
-rw-r--r--scene/main/viewport.cpp36
-rw-r--r--scene/main/viewport.h5
-rw-r--r--scene/register_scene_types.cpp28
-rw-r--r--scene/resources/audio_stream_resampled.cpp2
-rw-r--r--scene/resources/audio_stream_sample.cpp2
-rw-r--r--scene/resources/bit_mask.cpp2
-rw-r--r--scene/resources/curve.cpp8
-rw-r--r--scene/resources/curve.h4
-rw-r--r--scene/resources/default_theme/default_theme.cpp14
-rw-r--r--scene/resources/default_theme/hslider_grabber_disabled.pngbin0 -> 386 bytes
-rw-r--r--scene/resources/default_theme/theme_data.h8
-rw-r--r--scene/resources/default_theme/vslider_grabber_disabled.pngbin0 -> 335 bytes
-rw-r--r--scene/resources/dynamic_font.cpp4
-rw-r--r--scene/resources/environment.cpp49
-rw-r--r--scene/resources/environment.h8
-rw-r--r--scene/resources/font.cpp6
-rw-r--r--scene/resources/material.cpp376
-rw-r--r--scene/resources/material.h95
-rw-r--r--scene/resources/mesh.cpp21
-rw-r--r--scene/resources/mesh.h4
-rw-r--r--scene/resources/mesh_data_tool.cpp12
-rw-r--r--scene/resources/packed_scene.cpp4
-rw-r--r--scene/resources/primitive_meshes.cpp172
-rw-r--r--scene/resources/primitive_meshes.h26
-rw-r--r--scene/resources/scene_format_text.cpp26
-rw-r--r--scene/resources/sky_box.cpp29
-rw-r--r--scene/resources/sky_box.h5
-rw-r--r--scene/resources/style_box.cpp78
-rw-r--r--scene/resources/style_box.h34
-rw-r--r--scene/resources/surface_tool.cpp20
-rw-r--r--scene/resources/texture.cpp4
-rw-r--r--scene/resources/texture.h2
-rw-r--r--scene/resources/theme.cpp4
-rw-r--r--scene/resources/tile_set.cpp49
-rw-r--r--scene/resources/tile_set.h8
-rw-r--r--scene/resources/world.cpp7
-rw-r--r--scene/resources/world.h2
-rw-r--r--scene/resources/world_2d.cpp3
-rw-r--r--scene/resources/world_2d.h2
132 files changed, 4647 insertions, 2468 deletions
diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp
index a1ab51b3c8..22649cedd7 100644
--- a/scene/2d/animated_sprite.cpp
+++ b/scene/2d/animated_sprite.cpp
@@ -223,10 +223,10 @@ void SpriteFrames::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_animation_loop", "anim", "loop"), &SpriteFrames::set_animation_loop);
ClassDB::bind_method(D_METHOD("get_animation_loop", "anim"), &SpriteFrames::get_animation_loop);
- ClassDB::bind_method(D_METHOD("add_frame", "anim", "frame", "atpos"), &SpriteFrames::add_frame, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("add_frame", "anim", "frame:Texture", "atpos"), &SpriteFrames::add_frame, DEFVAL(-1));
ClassDB::bind_method(D_METHOD("get_frame_count", "anim"), &SpriteFrames::get_frame_count);
- ClassDB::bind_method(D_METHOD("get_frame", "anim", "idx"), &SpriteFrames::get_frame);
- ClassDB::bind_method(D_METHOD("set_frame", "anim", "idx", "txt"), &SpriteFrames::set_frame);
+ ClassDB::bind_method(D_METHOD("get_frame:Texture", "anim", "idx"), &SpriteFrames::get_frame);
+ ClassDB::bind_method(D_METHOD("set_frame", "anim", "idx", "txt:Texture"), &SpriteFrames::set_frame);
ClassDB::bind_method(D_METHOD("remove_frame", "anim", "idx"), &SpriteFrames::remove_frame);
ClassDB::bind_method(D_METHOD("clear", "anim"), &SpriteFrames::clear);
ClassDB::bind_method(D_METHOD("clear_all"), &SpriteFrames::clear_all);
diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp
index db22a38cec..841e2ef7d3 100644
--- a/scene/2d/area_2d.cpp
+++ b/scene/2d/area_2d.cpp
@@ -331,7 +331,10 @@ void Area2D::_clear_monitoring() {
Object *obj = ObjectDB::get_instance(E->key());
Node *node = obj ? obj->cast_to<Node>() : NULL;
- ERR_CONTINUE(!node);
+
+ if (!node) //node may have been deleted in previous frame or at other legiminate point
+ continue;
+ //ERR_CONTINUE(!node);
node->disconnect(SceneStringNames::get_singleton()->tree_entered, this, SceneStringNames::get_singleton()->_body_enter_tree);
node->disconnect(SceneStringNames::get_singleton()->tree_exited, this, SceneStringNames::get_singleton()->_body_exit_tree);
@@ -359,7 +362,7 @@ void Area2D::_clear_monitoring() {
Object *obj = ObjectDB::get_instance(E->key());
Node *node = obj ? obj->cast_to<Node>() : NULL;
- if (!node) //node may have been deleted in previous frame, this should not be an error
+ if (!node) //node may have been deleted in previous frame or at other legiminate point
continue;
//ERR_CONTINUE(!node);
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index 4a80aba355..40c25c8bf6 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -609,6 +609,27 @@ void CanvasItem::draw_line(const Point2 &p_from, const Point2 &p_to, const Color
VisualServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width, p_antialiased);
}
+void CanvasItem::draw_polyline(const Vector<Point2> &p_points, const Color &p_color, float p_width, bool p_antialiased) {
+
+ if (!drawing) {
+ ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
+ ERR_FAIL();
+ }
+
+ Vector<Color> colors;
+ colors.push_back(p_color);
+ VisualServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, colors, p_width, p_antialiased);
+}
+
+void CanvasItem::draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) {
+
+ if (!drawing) {
+ ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
+ ERR_FAIL();
+ }
+
+ VisualServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, p_colors, p_width, p_antialiased);
+}
void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled) {
if (!drawing) {
@@ -928,7 +949,7 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_canvas_item"), &CanvasItem::get_canvas_item);
- ClassDB::bind_method(D_METHOD("set_visible"), &CanvasItem::set_visible);
+ ClassDB::bind_method(D_METHOD("set_visible", "visible"), &CanvasItem::set_visible);
ClassDB::bind_method(D_METHOD("is_visible"), &CanvasItem::is_visible);
ClassDB::bind_method(D_METHOD("is_visible_in_tree"), &CanvasItem::is_visible_in_tree);
ClassDB::bind_method(D_METHOD("show"), &CanvasItem::show);
@@ -955,6 +976,8 @@ void CanvasItem::_bind_methods() {
//ClassDB::bind_method(D_METHOD("get_transform"),&CanvasItem::get_transform);
ClassDB::bind_method(D_METHOD("draw_line", "from", "to", "color", "width", "antialiased"), &CanvasItem::draw_line, DEFVAL(1.0), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("draw_polyline", "points", "color", "width", "antialiased"), &CanvasItem::draw_polyline, DEFVAL(1.0), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("draw_polyline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_polyline_colors, DEFVAL(1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_rect", "rect", "color", "filled"), &CanvasItem::draw_rect, DEFVAL(true));
ClassDB::bind_method(D_METHOD("draw_circle", "pos", "radius", "color"), &CanvasItem::draw_circle);
ClassDB::bind_method(D_METHOD("draw_texture", "texture:Texture", "pos", "modulate", "normal_map:Texture"), &CanvasItem::draw_texture, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(Variant()));
@@ -978,7 +1001,7 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_local_mouse_pos"), &CanvasItem::get_local_mouse_pos);
ClassDB::bind_method(D_METHOD("get_global_mouse_position"), &CanvasItem::get_global_mouse_position);
ClassDB::bind_method(D_METHOD("get_canvas"), &CanvasItem::get_canvas);
- ClassDB::bind_method(D_METHOD("get_world_2d"), &CanvasItem::get_world_2d);
+ ClassDB::bind_method(D_METHOD("get_world_2d:World2D"), &CanvasItem::get_world_2d);
//ClassDB::bind_method(D_METHOD("get_viewport"),&CanvasItem::get_viewport);
ClassDB::bind_method(D_METHOD("set_material", "material:Material"), &CanvasItem::set_material);
@@ -995,7 +1018,7 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("make_canvas_pos_local", "screen_point"),
&CanvasItem::make_canvas_pos_local);
- ClassDB::bind_method(D_METHOD("make_input_local", "event"), &CanvasItem::make_input_local);
+ ClassDB::bind_method(D_METHOD("make_input_local:InputEvent", "event:InputEvent"), &CanvasItem::make_input_local);
BIND_VMETHOD(MethodInfo("_draw"));
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index 06130e3252..27842727ac 100644
--- a/scene/2d/canvas_item.h
+++ b/scene/2d/canvas_item.h
@@ -242,6 +242,8 @@ public:
/* DRAWING API */
void draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0, bool p_antialiased = false);
+ void draw_polyline(const Vector<Point2> &p_points, const Color &p_color, float p_width = 1.0, bool p_antialiased = false);
+ void draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false);
void draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled = true);
void draw_circle(const Point2 &p_pos, float p_radius, const Color &p_color);
void draw_texture(const Ref<Texture> &p_texture, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1, 1), const Ref<Texture> &p_normal_map = Ref<Texture>());
diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp
index c5c274e225..eb47682884 100644
--- a/scene/2d/collision_object_2d.cpp
+++ b/scene/2d/collision_object_2d.cpp
@@ -152,6 +152,16 @@ void CollisionObject2D::get_shape_owners(List<uint32_t> *r_owners) {
}
}
+Array CollisionObject2D::_get_shape_owners() {
+
+ Array ret;
+ for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) {
+ ret.push_back(E->key());
+ }
+
+ return ret;
+}
+
void CollisionObject2D::shape_owner_set_transform(uint32_t p_owner, const Transform2D &p_transform) {
ERR_FAIL_COND(!shapes.has(p_owner));
@@ -204,10 +214,10 @@ int CollisionObject2D::shape_owner_get_shape_count(uint32_t p_owner) const {
return shapes[p_owner].shapes.size();
}
-Ref<Shape> CollisionObject2D::shape_owner_get_shape(uint32_t p_owner, int p_shape) const {
+Ref<Shape2D> CollisionObject2D::shape_owner_get_shape(uint32_t p_owner, int p_shape) const {
- ERR_FAIL_COND_V(!shapes.has(p_owner), Ref<Shape>());
- ERR_FAIL_INDEX_V(p_shape, shapes[p_owner].shapes.size(), Ref<Shape>());
+ ERR_FAIL_COND_V(!shapes.has(p_owner), Ref<Shape2D>());
+ ERR_FAIL_INDEX_V(p_shape, shapes[p_owner].shapes.size(), Ref<Shape2D>());
return shapes[p_owner].shapes[p_shape].shape;
}
@@ -323,6 +333,23 @@ void CollisionObject2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_pickable", "enabled"), &CollisionObject2D::set_pickable);
ClassDB::bind_method(D_METHOD("is_pickable"), &CollisionObject2D::is_pickable);
+ ClassDB::bind_method(D_METHOD("create_shape_owner", "owner:Object"), &CollisionObject2D::create_shape_owner);
+ ClassDB::bind_method(D_METHOD("remove_shape_owner", "owner_id"), &CollisionObject2D::remove_shape_owner);
+ ClassDB::bind_method(D_METHOD("get_shape_owners"), &CollisionObject2D::_get_shape_owners);
+ ClassDB::bind_method(D_METHOD("shape_owner_set_transform", "owner_id", "transform:Transform2D"), &CollisionObject2D::shape_owner_set_transform);
+ ClassDB::bind_method(D_METHOD("shape_owner_get_transform", "owner_id"), &CollisionObject2D::shape_owner_get_transform);
+ ClassDB::bind_method(D_METHOD("shape_owner_get_owner", "owner_id"), &CollisionObject2D::shape_owner_get_owner);
+ ClassDB::bind_method(D_METHOD("shape_owner_set_disabled", "owner_id", "disabled"), &CollisionObject2D::shape_owner_set_disabled);
+ ClassDB::bind_method(D_METHOD("is_shape_owner_disabled", "owner_id"), &CollisionObject2D::is_shape_owner_disabled);
+ ClassDB::bind_method(D_METHOD("shape_owner_set_one_way_collision", "owner_id", "enable"), &CollisionObject2D::shape_owner_set_one_way_collision);
+ ClassDB::bind_method(D_METHOD("is_shape_owner_one_way_collision_enabled", "owner_id"), &CollisionObject2D::is_shape_owner_one_way_collision_enabled);
+ ClassDB::bind_method(D_METHOD("shape_owner_add_shape", "owner_id", "shape:Shape2D"), &CollisionObject2D::shape_owner_add_shape);
+ ClassDB::bind_method(D_METHOD("shape_owner_get_shape_count", "owner_id"), &CollisionObject2D::shape_owner_get_shape_count);
+ ClassDB::bind_method(D_METHOD("shape_owner_get_shape", "owner_id", "shape_id"), &CollisionObject2D::shape_owner_get_shape);
+ ClassDB::bind_method(D_METHOD("shape_owner_get_shape_index", "owner_id", "shape_id"), &CollisionObject2D::shape_owner_get_shape_index);
+ ClassDB::bind_method(D_METHOD("shape_owner_remove_shape", "owner_id", "shape_id"), &CollisionObject2D::shape_owner_remove_shape);
+ ClassDB::bind_method(D_METHOD("shape_owner_clear_shapes", "owner_id"), &CollisionObject2D::shape_owner_clear_shapes);
+ ClassDB::bind_method(D_METHOD("shape_find_owner", "shape_index"), &CollisionObject2D::shape_find_owner);
BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "viewport"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::INT, "shape_idx")));
diff --git a/scene/2d/collision_object_2d.h b/scene/2d/collision_object_2d.h
index deffe8a002..36bf39ff4e 100644
--- a/scene/2d/collision_object_2d.h
+++ b/scene/2d/collision_object_2d.h
@@ -81,6 +81,7 @@ public:
uint32_t create_shape_owner(Object *p_owner);
void remove_shape_owner(uint32_t owner);
void get_shape_owners(List<uint32_t> *r_owners);
+ Array _get_shape_owners();
void shape_owner_set_transform(uint32_t p_owner, const Transform2D &p_transform);
Transform2D shape_owner_get_transform(uint32_t p_owner) const;
@@ -94,7 +95,7 @@ public:
void shape_owner_add_shape(uint32_t p_owner, const Ref<Shape2D> &p_shape);
int shape_owner_get_shape_count(uint32_t p_owner) const;
- Ref<Shape> shape_owner_get_shape(uint32_t p_owner, int p_shape) const;
+ Ref<Shape2D> shape_owner_get_shape(uint32_t p_owner, int p_shape) const;
int shape_owner_get_shape_index(uint32_t p_owner, int p_shape) const;
void shape_owner_remove_shape(uint32_t p_owner, int p_shape);
diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp
index ff4aa245ec..890ac0c1f3 100644
--- a/scene/2d/collision_shape_2d.cpp
+++ b/scene/2d/collision_shape_2d.cpp
@@ -201,8 +201,8 @@ bool CollisionShape2D::is_one_way_collision_enabled() const {
void CollisionShape2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_shape", "shape"), &CollisionShape2D::set_shape);
- ClassDB::bind_method(D_METHOD("get_shape"), &CollisionShape2D::get_shape);
+ ClassDB::bind_method(D_METHOD("set_shape", "shape:Shape2D"), &CollisionShape2D::set_shape);
+ ClassDB::bind_method(D_METHOD("get_shape:Shape2D"), &CollisionShape2D::get_shape);
ClassDB::bind_method(D_METHOD("set_disabled", "disabled"), &CollisionShape2D::set_disabled);
ClassDB::bind_method(D_METHOD("is_disabled"), &CollisionShape2D::is_disabled);
ClassDB::bind_method(D_METHOD("set_one_way_collision", "enabled"), &CollisionShape2D::set_one_way_collision);
diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp
index e8c2122bd1..044cb06c02 100644
--- a/scene/2d/light_2d.cpp
+++ b/scene/2d/light_2d.cpp
@@ -355,8 +355,8 @@ void Light2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_editor_only", "editor_only"), &Light2D::set_editor_only);
ClassDB::bind_method(D_METHOD("is_editor_only"), &Light2D::is_editor_only);
- ClassDB::bind_method(D_METHOD("set_texture", "texture"), &Light2D::set_texture);
- ClassDB::bind_method(D_METHOD("get_texture"), &Light2D::get_texture);
+ ClassDB::bind_method(D_METHOD("set_texture", "texture:Texture"), &Light2D::set_texture);
+ ClassDB::bind_method(D_METHOD("get_texture:Texture"), &Light2D::get_texture);
ClassDB::bind_method(D_METHOD("set_texture_offset", "texture_offset"), &Light2D::set_texture_offset);
ClassDB::bind_method(D_METHOD("get_texture_offset"), &Light2D::get_texture_offset);
diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp
index 5438557d0b..22e54cfb54 100644
--- a/scene/2d/line_2d.cpp
+++ b/scene/2d/line_2d.cpp
@@ -283,11 +283,11 @@ void Line2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_default_color", "color"), &Line2D::set_default_color);
ClassDB::bind_method(D_METHOD("get_default_color"), &Line2D::get_default_color);
- ClassDB::bind_method(D_METHOD("set_gradient", "color"), &Line2D::set_gradient);
- ClassDB::bind_method(D_METHOD("get_gradient"), &Line2D::get_gradient);
+ ClassDB::bind_method(D_METHOD("set_gradient", "color:Gradient"), &Line2D::set_gradient);
+ ClassDB::bind_method(D_METHOD("get_gradient:Gradient"), &Line2D::get_gradient);
- ClassDB::bind_method(D_METHOD("set_texture", "texture"), &Line2D::set_texture);
- ClassDB::bind_method(D_METHOD("get_texture"), &Line2D::get_texture);
+ ClassDB::bind_method(D_METHOD("set_texture", "texture:Texture"), &Line2D::set_texture);
+ ClassDB::bind_method(D_METHOD("get_texture:Texture"), &Line2D::get_texture);
ClassDB::bind_method(D_METHOD("set_texture_mode", "mode"), &Line2D::set_texture_mode);
ClassDB::bind_method(D_METHOD("get_texture_mode"), &Line2D::get_texture_mode);
diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp
index 6fe1dd73fe..0acc85681d 100644
--- a/scene/2d/node_2d.cpp
+++ b/scene/2d/node_2d.cpp
@@ -319,7 +319,7 @@ void Node2D::set_global_scale(const Size2 &p_scale) {
CanvasItem *pi = get_parent_item();
if (pi) {
const Size2 parent_global_scale = pi->get_global_transform().get_scale();
- set_scale(p_scale - parent_global_scale);
+ set_scale(p_scale / parent_global_scale);
} else {
set_scale(p_scale);
}
@@ -398,6 +398,16 @@ float Node2D::get_angle_to(const Vector2 &p_pos) const {
return (get_global_transform().affine_inverse().xform(p_pos)).angle();
}
+Point2 Node2D::to_local(Point2 p_global) const {
+
+ return get_global_transform().affine_inverse().xform(p_global);
+}
+
+Point2 Node2D::to_global(Point2 p_local) const {
+
+ return get_global_transform().xform(p_local);
+}
+
void Node2D::_bind_methods() {
// TODO: Obsolete those two methods (old name) properly (GH-4397)
@@ -436,6 +446,9 @@ void Node2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("look_at", "point"), &Node2D::look_at);
ClassDB::bind_method(D_METHOD("get_angle_to", "point"), &Node2D::get_angle_to);
+ ClassDB::bind_method(D_METHOD("to_local", "global_point"), &Node2D::to_local);
+ ClassDB::bind_method(D_METHOD("to_global", "local_point"), &Node2D::to_global);
+
ClassDB::bind_method(D_METHOD("set_z", "z"), &Node2D::set_z);
ClassDB::bind_method(D_METHOD("get_z"), &Node2D::get_z);
@@ -444,7 +457,7 @@ void Node2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("edit_set_pivot", "pivot"), &Node2D::edit_set_pivot);
- ClassDB::bind_method(D_METHOD("get_relative_transform_to_parent", "parent"), &Node2D::get_relative_transform_to_parent);
+ ClassDB::bind_method(D_METHOD("get_relative_transform_to_parent", "parent:Node"), &Node2D::get_relative_transform_to_parent);
ADD_GROUP("Transform", "");
ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "position"), "set_position", "get_position");
diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h
index 65331a4d58..5b3a28d5c3 100644
--- a/scene/2d/node_2d.h
+++ b/scene/2d/node_2d.h
@@ -104,6 +104,9 @@ public:
void look_at(const Vector2 &p_pos);
float get_angle_to(const Vector2 &p_pos) const;
+ Point2 to_local(Point2 p_global) const;
+ Point2 to_global(Point2 p_local) const;
+
void set_z_as_relative(bool p_enabled);
bool is_z_relative() const;
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index fd261117e1..8b2653f639 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -554,11 +554,12 @@ real_t RigidBody2D::get_inertia() const {
void RigidBody2D::set_weight(real_t p_weight) {
- set_mass(p_weight / 9.8);
+ set_mass(p_weight / real_t(GLOBAL_DEF("physics/2d/default_gravity", 98)) / 10);
}
+
real_t RigidBody2D::get_weight() const {
- return mass * 9.8;
+ return mass * real_t(GLOBAL_DEF("physics/2d/default_gravity", 98)) / 10;
}
void RigidBody2D::set_friction(real_t p_friction) {
diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp
index 5c1c953a37..4a68df5706 100644
--- a/scene/2d/polygon_2d.cpp
+++ b/scene/2d/polygon_2d.cpp
@@ -330,8 +330,8 @@ void Polygon2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_vertex_colors", "vertex_colors"), &Polygon2D::set_vertex_colors);
ClassDB::bind_method(D_METHOD("get_vertex_colors"), &Polygon2D::get_vertex_colors);
- ClassDB::bind_method(D_METHOD("set_texture", "texture"), &Polygon2D::set_texture);
- ClassDB::bind_method(D_METHOD("get_texture"), &Polygon2D::get_texture);
+ ClassDB::bind_method(D_METHOD("set_texture", "texture:Texture"), &Polygon2D::set_texture);
+ ClassDB::bind_method(D_METHOD("get_texture:Texture"), &Polygon2D::get_texture);
ClassDB::bind_method(D_METHOD("set_texture_offset", "texture_offset"), &Polygon2D::set_texture_offset);
ClassDB::bind_method(D_METHOD("get_texture_offset"), &Polygon2D::get_texture_offset);
diff --git a/scene/2d/remote_transform_2d.cpp b/scene/2d/remote_transform_2d.cpp
index 3cb9ebb5b5..4298377499 100644
--- a/scene/2d/remote_transform_2d.cpp
+++ b/scene/2d/remote_transform_2d.cpp
@@ -63,7 +63,50 @@ void RemoteTransform2D::_update_remote() {
return;
//todo make faster
- n->set_global_transform(get_global_transform());
+ if (use_global_coordinates) {
+
+ if (update_remote_position && update_remote_rotation && update_remote_scale) {
+ n->set_global_transform(get_global_transform());
+ } else {
+ Transform2D n_trans = n->get_global_transform();
+ Transform2D our_trans = get_global_transform();
+ Vector2 n_scale = n->get_global_scale();
+
+ if (!update_remote_position)
+ our_trans.set_origin(n_trans.get_origin());
+ if (!update_remote_rotation)
+ our_trans.set_rotation(n_trans.get_rotation());
+
+ n->set_global_transform(our_trans);
+
+ if (update_remote_scale)
+ n->set_scale(get_global_scale());
+ else
+ n->set_scale(n_scale);
+ }
+
+ } else {
+
+ if (update_remote_position && update_remote_rotation && update_remote_scale) {
+ n->set_transform(get_transform());
+ } else {
+ Transform2D n_trans = n->get_transform();
+ Transform2D our_trans = get_transform();
+ Vector2 n_scale = n->get_scale();
+
+ if (!update_remote_position)
+ our_trans.set_origin(n_trans.get_origin());
+ if (!update_remote_rotation)
+ our_trans.set_rotation(n_trans.get_rotation());
+
+ n->set_transform(our_trans);
+
+ if (update_remote_scale)
+ n->set_scale(get_scale());
+ else
+ n->set_scale(n_scale);
+ }
+ }
}
void RemoteTransform2D::_notification(int p_what) {
@@ -102,6 +145,41 @@ NodePath RemoteTransform2D::get_remote_node() const {
return remote_node;
}
+void RemoteTransform2D::set_use_global_coordinates(const bool p_enable) {
+ use_global_coordinates = p_enable;
+}
+
+bool RemoteTransform2D::get_use_global_coordinates() const {
+ return use_global_coordinates;
+}
+
+void RemoteTransform2D::set_update_position(const bool p_update) {
+ update_remote_position = p_update;
+ _update_remote();
+}
+
+bool RemoteTransform2D::get_update_position() const {
+ return update_remote_position;
+}
+
+void RemoteTransform2D::set_update_rotation(const bool p_update) {
+ update_remote_rotation = p_update;
+ _update_remote();
+}
+
+bool RemoteTransform2D::get_update_rotation() const {
+ return update_remote_rotation;
+}
+
+void RemoteTransform2D::set_update_scale(const bool p_update) {
+ update_remote_scale = p_update;
+ _update_remote();
+}
+
+bool RemoteTransform2D::get_update_scale() const {
+ return update_remote_scale;
+}
+
String RemoteTransform2D::get_configuration_warning() const {
if (!has_node(remote_node) || !get_node(remote_node) || !get_node(remote_node)->cast_to<Node2D>()) {
@@ -116,11 +194,32 @@ void RemoteTransform2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_remote_node", "path"), &RemoteTransform2D::set_remote_node);
ClassDB::bind_method(D_METHOD("get_remote_node"), &RemoteTransform2D::get_remote_node);
+ ClassDB::bind_method(D_METHOD("set_use_global_coordinates", "use_global_coordinates"), &RemoteTransform2D::set_use_global_coordinates);
+ ClassDB::bind_method(D_METHOD("get_use_global_coordinates"), &RemoteTransform2D::get_use_global_coordinates);
+
+ ClassDB::bind_method(D_METHOD("set_update_position", "update_remote_position"), &RemoteTransform2D::set_update_position);
+ ClassDB::bind_method(D_METHOD("get_update_position"), &RemoteTransform2D::get_update_position);
+ ClassDB::bind_method(D_METHOD("set_update_rotation", "update_remote_rotation"), &RemoteTransform2D::set_update_rotation);
+ ClassDB::bind_method(D_METHOD("get_update_rotation"), &RemoteTransform2D::get_update_rotation);
+ ClassDB::bind_method(D_METHOD("set_update_scale", "update_remote_scale"), &RemoteTransform2D::set_update_scale);
+ ClassDB::bind_method(D_METHOD("get_update_scale"), &RemoteTransform2D::get_update_scale);
+
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "remote_path"), "set_remote_node", "get_remote_node");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_global_coordinates"), "set_use_global_coordinates", "get_use_global_coordinates");
+
+ ADD_GROUP("Update", "update_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_position"), "set_update_position", "get_update_position");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_rotation"), "set_update_rotation", "get_update_rotation");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_scale"), "set_update_scale", "get_update_scale");
}
RemoteTransform2D::RemoteTransform2D() {
+ use_global_coordinates = true;
+ update_remote_position = true;
+ update_remote_rotation = true;
+ update_remote_scale = true;
+
cache = 0;
set_notify_transform(true);
}
diff --git a/scene/2d/remote_transform_2d.h b/scene/2d/remote_transform_2d.h
index 375efabf2f..d58ec14a95 100644
--- a/scene/2d/remote_transform_2d.h
+++ b/scene/2d/remote_transform_2d.h
@@ -37,6 +37,11 @@ class RemoteTransform2D : public Node2D {
ObjectID cache;
+ bool use_global_coordinates;
+ bool update_remote_position;
+ bool update_remote_rotation;
+ bool update_remote_scale;
+
void _update_remote();
void _update_cache();
//void _node_exited_scene();
@@ -48,6 +53,18 @@ public:
void set_remote_node(const NodePath &p_remote_node);
NodePath get_remote_node() const;
+ void set_use_global_coordinates(const bool p_enable);
+ bool get_use_global_coordinates() const;
+
+ void set_update_position(const bool p_update);
+ bool get_update_position() const;
+
+ void set_update_rotation(const bool p_update);
+ bool get_update_rotation() const;
+
+ void set_update_scale(const bool p_update);
+ bool get_update_scale() const;
+
virtual String get_configuration_warning() const;
RemoteTransform2D();
diff --git a/scene/2d/screen_button.cpp b/scene/2d/screen_button.cpp
index 37139b2b93..24c9137807 100644
--- a/scene/2d/screen_button.cpp
+++ b/scene/2d/screen_button.cpp
@@ -356,17 +356,17 @@ bool TouchScreenButton::is_passby_press_enabled() const {
void TouchScreenButton::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_texture", "texture"), &TouchScreenButton::set_texture);
- ClassDB::bind_method(D_METHOD("get_texture"), &TouchScreenButton::get_texture);
+ ClassDB::bind_method(D_METHOD("set_texture", "texture:Texture"), &TouchScreenButton::set_texture);
+ ClassDB::bind_method(D_METHOD("get_texture:Texture"), &TouchScreenButton::get_texture);
- ClassDB::bind_method(D_METHOD("set_texture_pressed", "texture_pressed"), &TouchScreenButton::set_texture_pressed);
- ClassDB::bind_method(D_METHOD("get_texture_pressed"), &TouchScreenButton::get_texture_pressed);
+ ClassDB::bind_method(D_METHOD("set_texture_pressed", "texture_pressed:Texture"), &TouchScreenButton::set_texture_pressed);
+ ClassDB::bind_method(D_METHOD("get_texture_pressed:Texture"), &TouchScreenButton::get_texture_pressed);
- ClassDB::bind_method(D_METHOD("set_bitmask", "bitmask"), &TouchScreenButton::set_bitmask);
- ClassDB::bind_method(D_METHOD("get_bitmask"), &TouchScreenButton::get_bitmask);
+ ClassDB::bind_method(D_METHOD("set_bitmask", "bitmask:BitMap"), &TouchScreenButton::set_bitmask);
+ ClassDB::bind_method(D_METHOD("get_bitmask:BitMap"), &TouchScreenButton::get_bitmask);
- ClassDB::bind_method(D_METHOD("set_shape", "shape"), &TouchScreenButton::set_shape);
- ClassDB::bind_method(D_METHOD("get_shape"), &TouchScreenButton::get_shape);
+ ClassDB::bind_method(D_METHOD("set_shape", "shape:Shape2D"), &TouchScreenButton::set_shape);
+ ClassDB::bind_method(D_METHOD("get_shape:Shape2D"), &TouchScreenButton::get_shape);
ClassDB::bind_method(D_METHOD("set_shape_centered", "bool"), &TouchScreenButton::set_shape_centered);
ClassDB::bind_method(D_METHOD("is_shape_centered"), &TouchScreenButton::is_shape_centered);
diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp
index c4590c100d..ad34dfd63a 100644
--- a/scene/2d/sprite.cpp
+++ b/scene/2d/sprite.cpp
@@ -105,20 +105,7 @@ void Sprite::set_texture(const Ref<Texture> &p_texture) {
if (p_texture == texture)
return;
-#ifdef DEBUG_ENABLED
- if (texture.is_valid()) {
- texture->disconnect(CoreStringNames::get_singleton()->changed, this, SceneStringNames::get_singleton()->update);
- }
-#endif
texture = p_texture;
- /* this should no longer be needed in 3.0
-#ifdef DEBUG_ENABLED
- if (texture.is_valid()) {
- texture->set_flags(texture->get_flags()); //remove repeat from texture, it looks bad in sprites
- texture->connect(CoreStringNames::get_singleton()->changed, this, SceneStringNames::get_singleton()->update);
- }
-#endif
-*/
update();
emit_signal("texture_changed");
item_rect_changed();
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 57e25ec609..9d70b75027 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -461,16 +461,18 @@ void TileMap::_update_dirty_quadrants() {
Transform2D xform;
xform.set_origin(offset.floor());
- _fix_cell_transform(xform, c, shapes[i].shape_offset + center_ofs, s);
+ _fix_cell_transform(xform, c, center_ofs, s);
+
+ xform *= shapes[i].shape_transform;
if (debug_canvas_item.is_valid()) {
vs->canvas_item_add_set_transform(debug_canvas_item, xform);
shape->draw(debug_canvas_item, debug_collision_color);
}
ps->body_add_shape(q.body, shape->get_rid(), xform);
- shape_idx++;
- ps->body_set_shape_as_one_way_collision(q.body, shape_idx, shapes[i].one_way_collision);
ps->body_set_shape_metadata(q.body, shape_idx, Vector2(E->key().x, E->key().y));
+ ps->body_set_shape_as_one_way_collision(q.body, shape_idx, shapes[i].one_way_collision);
+ shape_idx++;
}
}
diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp
index 39a4e926b2..59227070b3 100644
--- a/scene/3d/area.cpp
+++ b/scene/3d/area.cpp
@@ -29,7 +29,9 @@
/*************************************************************************/
#include "area.h"
#include "scene/scene_string_names.h"
+#include "servers/audio_server.h"
#include "servers/physics_server.h"
+
void Area::set_space_override_mode(SpaceOverride p_mode) {
space_override = p_mode;
@@ -227,7 +229,11 @@ void Area::_clear_monitoring() {
Object *obj = ObjectDB::get_instance(E->key());
Node *node = obj ? obj->cast_to<Node>() : NULL;
- ERR_CONTINUE(!node);
+
+ if (!node) //node may have been deleted in previous frame or at other legiminate point
+ continue;
+ //ERR_CONTINUE(!node);
+
if (!E->get().in_tree)
continue;
@@ -253,7 +259,11 @@ void Area::_clear_monitoring() {
Object *obj = ObjectDB::get_instance(E->key());
Node *node = obj ? obj->cast_to<Node>() : NULL;
- ERR_CONTINUE(!node);
+
+ if (!node) //node may have been deleted in previous frame or at other legiminate point
+ continue;
+ //ERR_CONTINUE(!node);
+
if (!E->get().in_tree)
continue;
@@ -530,6 +540,87 @@ bool Area::get_collision_layer_bit(int p_bit) const {
return get_collision_layer() & (1 << p_bit);
}
+void Area::set_audio_bus_override(bool p_override) {
+
+ audio_bus_override = p_override;
+}
+
+bool Area::is_overriding_audio_bus() const {
+
+ return audio_bus_override;
+}
+
+void Area::set_audio_bus(const StringName &p_audio_bus) {
+
+ audio_bus = p_audio_bus;
+}
+StringName Area::get_audio_bus() const {
+
+ for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
+ if (AudioServer::get_singleton()->get_bus_name(i) == audio_bus) {
+ return audio_bus;
+ }
+ }
+ return "Master";
+}
+
+void Area::set_use_reverb_bus(bool p_enable) {
+
+ use_reverb_bus = p_enable;
+}
+bool Area::is_using_reverb_bus() const {
+
+ return use_reverb_bus;
+}
+
+void Area::set_reverb_bus(const StringName &p_audio_bus) {
+
+ reverb_bus = p_audio_bus;
+}
+StringName Area::get_reverb_bus() const {
+
+ for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
+ if (AudioServer::get_singleton()->get_bus_name(i) == reverb_bus) {
+ return reverb_bus;
+ }
+ }
+ return "Master";
+}
+
+void Area::set_reverb_amount(float p_amount) {
+
+ reverb_amount = p_amount;
+}
+float Area::get_reverb_amount() const {
+
+ return reverb_amount;
+}
+
+void Area::set_reverb_uniformity(float p_uniformity) {
+
+ reverb_uniformity = p_uniformity;
+}
+float Area::get_reverb_uniformity() const {
+
+ return reverb_uniformity;
+}
+
+void Area::_validate_property(PropertyInfo &property) const {
+
+ if (property.name == "audio_bus_name" || property.name == "reverb_bus_name") {
+
+ String options;
+ for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
+ if (i > 0)
+ options += ",";
+ String name = AudioServer::get_singleton()->get_bus_name(i);
+ options += name;
+ }
+
+ property.hint_string = options;
+ }
+}
+
void Area::_bind_methods() {
ClassDB::bind_method(D_METHOD("_body_enter_tree", "id"), &Area::_body_enter_tree);
@@ -589,6 +680,24 @@ void Area::_bind_methods() {
ClassDB::bind_method(D_METHOD("_body_inout"), &Area::_body_inout);
ClassDB::bind_method(D_METHOD("_area_inout"), &Area::_area_inout);
+ ClassDB::bind_method(D_METHOD("set_audio_bus_override", "enable"), &Area::set_audio_bus_override);
+ ClassDB::bind_method(D_METHOD("is_overriding_audio_bus"), &Area::is_overriding_audio_bus);
+
+ ClassDB::bind_method(D_METHOD("set_audio_bus", "name"), &Area::set_audio_bus);
+ ClassDB::bind_method(D_METHOD("get_audio_bus"), &Area::get_audio_bus);
+
+ ClassDB::bind_method(D_METHOD("set_use_reverb_bus", "enable"), &Area::set_use_reverb_bus);
+ ClassDB::bind_method(D_METHOD("is_using_reverb_bus"), &Area::is_using_reverb_bus);
+
+ ClassDB::bind_method(D_METHOD("set_reverb_bus", "name"), &Area::set_reverb_bus);
+ ClassDB::bind_method(D_METHOD("get_reverb_bus"), &Area::get_reverb_bus);
+
+ ClassDB::bind_method(D_METHOD("set_reverb_amount", "amount"), &Area::set_reverb_amount);
+ ClassDB::bind_method(D_METHOD("get_reverb_amount"), &Area::get_reverb_amount);
+
+ ClassDB::bind_method(D_METHOD("set_reverb_uniformity", "amount"), &Area::set_reverb_uniformity);
+ ClassDB::bind_method(D_METHOD("get_reverb_uniformity"), &Area::get_reverb_uniformity);
+
ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "area_shape")));
ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "area_shape")));
ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body")));
@@ -612,6 +721,14 @@ void Area::_bind_methods() {
ADD_GROUP("Collision", "collision_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
+ ADD_GROUP("Audio Bus", "audio_bus_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_bus_override"), "set_audio_bus_override", "is_overriding_audio_bus");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "audio_bus_name", PROPERTY_HINT_ENUM, ""), "set_audio_bus", "get_audio_bus");
+ ADD_GROUP("Reverb Bus", "reverb_bus_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "reverb_bus_enable"), "set_use_reverb_bus", "is_using_reverb_bus");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "reverb_bus_name", PROPERTY_HINT_ENUM, ""), "set_reverb_bus", "get_reverb_bus");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "reverb_bus_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_reverb_amount", "get_reverb_amount");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "reverb_bus_uniformity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_reverb_uniformity", "get_reverb_uniformity");
}
Area::Area()
@@ -632,6 +749,14 @@ Area::Area()
set_ray_pickable(false);
set_monitoring(true);
set_monitorable(true);
+
+ audio_bus_override = false;
+ audio_bus = "Master";
+
+ use_reverb_bus = false;
+ reverb_bus = "Master";
+ reverb_amount = 0.0;
+ reverb_uniformity = 0.0;
}
Area::~Area() {
diff --git a/scene/3d/area.h b/scene/3d/area.h
index 279a52ee69..5df308fc47 100644
--- a/scene/3d/area.h
+++ b/scene/3d/area.h
@@ -126,6 +126,16 @@ private:
Map<ObjectID, AreaState> area_map;
void _clear_monitoring();
+ bool audio_bus_override;
+ StringName audio_bus;
+
+ bool use_reverb_bus;
+ StringName reverb_bus;
+ float reverb_amount;
+ float reverb_uniformity;
+
+ void _validate_property(PropertyInfo &property) const;
+
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -179,6 +189,24 @@ public:
bool overlaps_area(Node *p_area) const;
bool overlaps_body(Node *p_body) const;
+ void set_audio_bus_override(bool p_override);
+ bool is_overriding_audio_bus() const;
+
+ void set_audio_bus(const StringName &p_audio_bus);
+ StringName get_audio_bus() const;
+
+ void set_use_reverb_bus(bool p_enable);
+ bool is_using_reverb_bus() const;
+
+ void set_reverb_bus(const StringName &p_audio_bus);
+ StringName get_reverb_bus() const;
+
+ void set_reverb_amount(float p_amount);
+ float get_reverb_amount() const;
+
+ void set_reverb_uniformity(float p_uniformity);
+ float get_reverb_uniformity() const;
+
Area();
~Area();
};
diff --git a/scene/3d/arvr_nodes.cpp b/scene/3d/arvr_nodes.cpp
new file mode 100644
index 0000000000..5f2a720748
--- /dev/null
+++ b/scene/3d/arvr_nodes.cpp
@@ -0,0 +1,313 @@
+/*************************************************************************/
+/* arvr_nodes.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (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 "arvr_nodes.h"
+#include "core/os/input.h"
+#include "servers/arvr/arvr_interface.h"
+#include "servers/arvr/arvr_positional_tracker.h"
+#include "servers/arvr_server.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void ARVRCamera::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ // need to find our ARVROrigin parent and let it know we're it's camera!
+ ARVROrigin *origin = get_parent()->cast_to<ARVROrigin>();
+ if (origin != NULL) {
+ origin->set_tracked_camera(this);
+ }
+ }; break;
+ case NOTIFICATION_EXIT_TREE: {
+ // need to find our ARVROrigin parent and let it know we're no longer it's camera!
+ ARVROrigin *origin = get_parent()->cast_to<ARVROrigin>();
+ if (origin != NULL) {
+ origin->clear_tracked_camera_if(this);
+ }
+ }; break;
+ };
+};
+
+String ARVRCamera::get_configuration_warning() const {
+ if (!is_visible() || !is_inside_tree())
+ return String();
+
+ // must be child node of ARVROrigin!
+ ARVROrigin *origin = get_parent()->cast_to<ARVROrigin>();
+ if (origin == NULL) {
+ return TTR("ARVRCamera must have an ARVROrigin node as its parent");
+ };
+
+ return String();
+};
+
+ARVRCamera::ARVRCamera(){
+ // nothing to do here yet for now..
+};
+
+ARVRCamera::~ARVRCamera(){
+ // nothing to do here yet for now..
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void ARVRController::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ set_process_internal(true);
+ }; break;
+ case NOTIFICATION_EXIT_TREE: {
+ set_process_internal(false);
+ }; break;
+ case NOTIFICATION_INTERNAL_PROCESS: {
+ // get our ARVRServer
+ ARVRServer *arvr_server = ARVRServer::get_singleton();
+ ERR_FAIL_NULL(arvr_server);
+
+ // find the tracker for our controller
+ ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, controller_id);
+ if (tracker == NULL) {
+ // this controller is currently turned off
+ is_active = false;
+ button_states = 0;
+ } else {
+ set_transform(tracker->get_transform(true));
+
+ int joy_id = tracker->get_joy_id();
+ if (joy_id >= 0) {
+ int mask = 1;
+ // check button states
+ for (int i = 0; i < 16; i++) {
+ bool was_pressed = (button_states && mask) == mask;
+ bool is_pressed = Input::get_singleton()->is_joy_button_pressed(joy_id, i);
+
+ if (!was_pressed && is_pressed) {
+ emit_signal("button_pressed", i);
+ button_states += mask;
+ } else if (was_pressed && !is_pressed) {
+ emit_signal("button_release", i);
+ button_states -= mask;
+ };
+
+ mask = mask << 1;
+ };
+
+ } else {
+ button_states = 0;
+ };
+ };
+ }; break;
+ default:
+ break;
+ };
+};
+
+void ARVRController::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_controller_id", "controller_id"), &ARVRController::set_controller_id);
+ ClassDB::bind_method(D_METHOD("get_controller_id"), &ARVRController::get_controller_id);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "controller_id"), "set_controller_id", "get_controller_id");
+ ClassDB::bind_method(D_METHOD("get_controller_name"), &ARVRController::get_controller_name);
+
+ // passthroughs to information about our related joystick
+ ClassDB::bind_method(D_METHOD("get_joystick_id"), &ARVRController::get_joystick_id);
+ ClassDB::bind_method(D_METHOD("is_button_pressed", "button"), &ARVRController::is_button_pressed);
+ ClassDB::bind_method(D_METHOD("get_joystick_axis", "axis"), &ARVRController::get_joystick_axis);
+
+ ClassDB::bind_method(D_METHOD("get_is_active"), &ARVRController::get_is_active);
+
+ ADD_SIGNAL(MethodInfo("button_pressed", PropertyInfo(Variant::INT, "button")));
+ ADD_SIGNAL(MethodInfo("button_release", PropertyInfo(Variant::INT, "button")));
+};
+
+void ARVRController::set_controller_id(int p_controller_id) {
+ // we don't check any bounds here, this controller may not yet be active and just be a place holder until it is.
+ controller_id = p_controller_id;
+};
+
+int ARVRController::get_controller_id(void) const {
+ return controller_id;
+};
+
+String ARVRController::get_controller_name(void) const {
+ // get our ARVRServer
+ ARVRServer *arvr_server = ARVRServer::get_singleton();
+ ERR_FAIL_NULL_V(arvr_server, String());
+
+ ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, controller_id);
+ if (tracker == NULL) {
+ return String("Not connected");
+ };
+
+ return tracker->get_name();
+};
+
+int ARVRController::get_joystick_id() const {
+ // get our ARVRServer
+ ARVRServer *arvr_server = ARVRServer::get_singleton();
+ ERR_FAIL_NULL_V(arvr_server, 0);
+
+ ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, controller_id);
+ if (tracker == NULL) {
+ return 0;
+ };
+
+ return tracker->get_joy_id();
+};
+
+int ARVRController::is_button_pressed(int p_button) const {
+ int joy_id = get_joystick_id();
+ if (joy_id == 0) {
+ return false;
+ };
+
+ return Input::get_singleton()->is_joy_button_pressed(joy_id, p_button);
+};
+
+float ARVRController::get_joystick_axis(int p_axis) const {
+ int joy_id = get_joystick_id();
+ if (joy_id == 0) {
+ return 0.0;
+ };
+
+ return Input::get_singleton()->get_joy_axis(joy_id, p_axis);
+};
+
+bool ARVRController::get_is_active() const {
+ return is_active;
+};
+
+String ARVRController::get_configuration_warning() const {
+ if (!is_visible() || !is_inside_tree())
+ return String();
+
+ // must be child node of ARVROrigin!
+ ARVROrigin *origin = get_parent()->cast_to<ARVROrigin>();
+ if (origin == NULL) {
+ return TTR("ARVRController must have an ARVROrigin node as its parent");
+ };
+
+ if (controller_id == 0) {
+ return TTR("The controller id must not be 0 or this controller will not be bound to an actual controller");
+ };
+
+ return String();
+};
+
+ARVRController::ARVRController() {
+ controller_id = 0;
+ is_active = true;
+};
+
+ARVRController::~ARVRController(){
+ // nothing to do here yet for now..
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+String ARVROrigin::get_configuration_warning() const {
+ if (!is_visible() || !is_inside_tree())
+ return String();
+
+ if (tracked_camera == NULL)
+ return TTR("ARVROrigin requires an ARVRCamera child node");
+
+ return String();
+};
+
+void ARVROrigin::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_world_scale", "world_scale"), &ARVROrigin::set_world_scale);
+ ClassDB::bind_method(D_METHOD("get_world_scale"), &ARVROrigin::get_world_scale);
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "world_scale"), "set_world_scale", "get_world_scale");
+};
+
+void ARVROrigin::set_tracked_camera(ARVRCamera *p_tracked_camera) {
+ tracked_camera = p_tracked_camera;
+};
+
+void ARVROrigin::clear_tracked_camera_if(ARVRCamera *p_tracked_camera) {
+ if (tracked_camera == p_tracked_camera) {
+ tracked_camera = NULL;
+ };
+};
+
+float ARVROrigin::get_world_scale() const {
+ // get our ARVRServer
+ ARVRServer *arvr_server = ARVRServer::get_singleton();
+ ERR_FAIL_NULL_V(arvr_server, 1.0);
+
+ return arvr_server->get_world_scale();
+};
+
+void ARVROrigin::set_world_scale(float p_world_scale) {
+ // get our ARVRServer
+ ARVRServer *arvr_server = ARVRServer::get_singleton();
+ ERR_FAIL_NULL(arvr_server);
+
+ arvr_server->set_world_scale(p_world_scale);
+};
+
+void ARVROrigin::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ set_process_internal(true);
+ }; break;
+ case NOTIFICATION_EXIT_TREE: {
+ set_process_internal(false);
+ }; break;
+ case NOTIFICATION_INTERNAL_PROCESS: {
+ // get our ARVRServer
+ ARVRServer *arvr_server = ARVRServer::get_singleton();
+ ERR_FAIL_NULL(arvr_server);
+
+ // set our world origin to our node transform
+ arvr_server->set_world_origin(get_global_transform());
+
+ // check if we have a primary interface
+ Ref<ARVRInterface> arvr_interface = arvr_server->get_primary_interface();
+ if (arvr_interface.is_valid() && tracked_camera != NULL) {
+ // get our positioning transform for our headset
+ Transform t = arvr_interface->get_transform_for_eye(ARVRInterface::EYE_MONO, Transform());
+
+ // now apply this to our camera
+ tracked_camera->set_transform(t);
+ };
+ }; break;
+ default:
+ break;
+ };
+};
+
+ARVROrigin::ARVROrigin() {
+ tracked_camera = NULL;
+};
+
+ARVROrigin::~ARVROrigin(){
+ // nothing to do here yet for now..
+};
diff --git a/scene/3d/arvr_nodes.h b/scene/3d/arvr_nodes.h
new file mode 100644
index 0000000000..3dab263317
--- /dev/null
+++ b/scene/3d/arvr_nodes.h
@@ -0,0 +1,126 @@
+/*************************************************************************/
+/* arvr_nodes.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (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 ARVR_NODES_H
+#define ARVR_NODES_H
+
+#include "scene/3d/camera.h"
+#include "scene/3d/spatial.h"
+
+/**
+ @author Bastiaan Olij <mux213@gmail.com>
+**/
+
+/*
+ ARVRCamera is a subclass of camera which will register itself with its parent ARVROrigin and as a result is automatically positioned
+*/
+class ARVRCamera : public Camera {
+
+ GDCLASS(ARVRCamera, Camera);
+
+protected:
+ void _notification(int p_what);
+
+public:
+ String get_configuration_warning() const;
+
+ ARVRCamera();
+ ~ARVRCamera();
+};
+
+/*
+ ARVRController is a helper node that automatically updates it's position based on tracker data.
+
+ It must be a child node of our ARVROrigin node
+*/
+
+class ARVRController : public Spatial {
+
+ GDCLASS(ARVRController, Spatial);
+
+private:
+ int controller_id;
+ bool is_active;
+ int button_states;
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ void set_controller_id(int p_controller_id);
+ int get_controller_id(void) const;
+ String get_controller_name(void) const;
+
+ int get_joystick_id() const;
+ int is_button_pressed(int p_button) const;
+ float get_joystick_axis(int p_axis) const;
+
+ bool get_is_active() const;
+
+ String get_configuration_warning() const;
+
+ ARVRController();
+ ~ARVRController();
+};
+
+/*
+ ARVROrigin is special spatial node that acts as our origin point mapping our real world center of our tracking volume into our virtual world.
+
+ It is this point that you will move around the world as the player 'moves while standing still', i.e. the player moves through teleporting or controller inputs as opposed to physically moving.
+
+ Our camera and controllers will always be child nodes and thus place relative to this origin point.
+ This node will automatically locate any camera child nodes and update its position while our ARVRController node will handle tracked controllers.
+*/
+class ARVROrigin : public Spatial {
+
+ GDCLASS(ARVROrigin, Spatial);
+
+private:
+ ARVRCamera *tracked_camera;
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ String get_configuration_warning() const;
+
+ void set_tracked_camera(ARVRCamera *p_tracked_camera);
+ void clear_tracked_camera_if(ARVRCamera *p_tracked_camera);
+
+ float get_world_scale() const;
+ void set_world_scale(float p_world_scale);
+
+ ARVROrigin();
+ ~ARVROrigin();
+};
+
+#endif /* ARVR_NODES_H */
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
new file mode 100644
index 0000000000..87ea018425
--- /dev/null
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -0,0 +1,930 @@
+#include "audio_stream_player_3d.h"
+#include "engine.h"
+#include "scene/3d/area.h"
+#include "scene/3d/camera.h"
+#include "scene/main/viewport.h"
+void AudioStreamPlayer3D::_mix_audio() {
+
+ if (!stream_playback.is_valid()) {
+ return;
+ }
+
+ if (!active) {
+ return;
+ }
+
+ bool started = false;
+ if (setseek >= 0.0) {
+ stream_playback->start(setseek);
+ setseek = -1.0; //reset seek
+ started = true;
+ }
+
+ //get data
+ AudioFrame *buffer = mix_buffer.ptr();
+ int buffer_size = mix_buffer.size();
+
+ //mix
+ if (output_count > 0 || out_of_range_mode == OUT_OF_RANGE_MIX) {
+
+ float pitch_scale = 0.0;
+ if (output_count) {
+ //used for doppler, not realistic but good enough
+ for (int i = 0; i < output_count; i++) {
+ pitch_scale += outputs[i].pitch_scale;
+ }
+ pitch_scale /= float(output_count);
+ } else {
+ pitch_scale = 1.0;
+ }
+
+ stream_playback->mix(buffer, pitch_scale, buffer_size);
+ }
+
+ //write all outputs
+ for (int i = 0; i < output_count; i++) {
+
+ Output current = outputs[i];
+
+ //see if current output exists, to keep volume ramp
+ bool found = false;
+ for (int j = i; j < prev_output_count; j++) {
+ if (prev_outputs[j].viewport == current.viewport) {
+ if (j != i) {
+ SWAP(prev_outputs[j], prev_outputs[i]);
+ }
+ found = true;
+ break;
+ }
+ }
+
+ bool interpolate_filter = !started;
+ ;
+ if (!found) {
+ //create new if was not used before
+ if (prev_output_count < MAX_OUTPUTS) {
+ prev_outputs[prev_output_count] = prev_outputs[i]; //may be owned by another viewport
+ prev_output_count++;
+ }
+ prev_outputs[i] = current;
+ interpolate_filter = false;
+ }
+
+ //mix!
+
+ int buffers = 0;
+ int first = 0;
+
+ switch (AudioServer::get_singleton()->get_speaker_mode()) {
+
+ case AudioServer::SPEAKER_MODE_STEREO: {
+ buffers = 1;
+ first = 0;
+
+ } break;
+ case AudioServer::SPEAKER_SURROUND_51: {
+ buffers = 2;
+ first = 1;
+
+ } break;
+ case AudioServer::SPEAKER_SURROUND_71: {
+
+ buffers = 3;
+ first = 1;
+
+ } break;
+ }
+
+ for (int k = 0; k < buffers; k++) {
+ AudioFrame vol_inc = (current.vol[k] - prev_outputs[i].vol[k]) / float(buffer_size);
+ AudioFrame vol = current.vol[k];
+
+ AudioFrame *target = AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, first + k);
+
+ current.filter.set_mode(AudioFilterSW::HIGHSHELF);
+ current.filter.set_sampling_rate(AudioServer::get_singleton()->get_mix_rate());
+ current.filter.set_cutoff(attenuation_filter_cutoff_hz);
+ current.filter.set_resonance(1);
+ current.filter.set_stages(1);
+ current.filter.set_gain(current.filter_gain);
+
+ if (interpolate_filter) {
+
+ current.filter_process[k * 2 + 0] = prev_outputs[i].filter_process[k * 2 + 0];
+ current.filter_process[k * 2 + 1] = prev_outputs[i].filter_process[k * 2 + 1];
+
+ current.filter_process[k * 2 + 0].set_filter(&current.filter, false);
+ current.filter_process[k * 2 + 1].set_filter(&current.filter, false);
+
+ current.filter_process[k * 2 + 0].update_coeffs(buffer_size);
+ current.filter_process[k * 2 + 1].update_coeffs(buffer_size);
+ for (int j = 0; j < buffer_size; j++) {
+
+ AudioFrame f = buffer[j] * vol;
+ current.filter_process[k * 2 + 0].process_one_interp(f.l);
+ current.filter_process[k * 2 + 1].process_one_interp(f.r);
+
+ target[j] += f;
+ vol += vol_inc;
+ }
+ } else {
+ current.filter_process[k * 2 + 0].set_filter(&current.filter);
+ current.filter_process[k * 2 + 1].set_filter(&current.filter);
+
+ current.filter_process[k * 2 + 0].update_coeffs();
+ current.filter_process[k * 2 + 1].update_coeffs();
+ for (int j = 0; j < buffer_size; j++) {
+
+ AudioFrame f = buffer[j] * vol;
+ current.filter_process[k * 2 + 0].process_one(f.l);
+ current.filter_process[k * 2 + 1].process_one(f.r);
+
+ target[j] += f;
+ vol += vol_inc;
+ }
+ }
+
+ if (current.reverb_bus_index >= 0) {
+
+ AudioFrame *rtarget = AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.reverb_bus_index, first + k);
+
+ if (current.reverb_bus_index == prev_outputs[i].reverb_bus_index) {
+ AudioFrame rvol_inc = (current.reverb_vol[k] - prev_outputs[i].reverb_vol[k]) / float(buffer_size);
+ AudioFrame rvol = prev_outputs[i].reverb_vol[k];
+
+ for (int j = 0; j < buffer_size; j++) {
+
+ rtarget[j] += buffer[j] * rvol;
+ rvol += rvol_inc;
+ }
+ } else {
+
+ AudioFrame rvol = current.reverb_vol[k];
+ for (int j = 0; j < buffer_size; j++) {
+
+ rtarget[j] += buffer[j] * rvol;
+ }
+ }
+ }
+ }
+
+ prev_outputs[i] = current;
+ }
+
+ prev_output_count = output_count;
+
+ //stream is no longer active, disable this.
+ if (!stream_playback->is_playing()) {
+ active = false;
+ }
+
+ output_ready = false;
+}
+
+float AudioStreamPlayer3D::_get_attenuation_db(float p_distance) const {
+
+ float att;
+ switch (attenuation_model) {
+ case ATTENUATION_INVERSE_DISTANCE: {
+ att = Math::linear2db(1.0 / ((p_distance / unit_size) + 000001));
+ } break;
+ case ATTENUATION_INVERSE_SQUARE_DISTANCE: {
+ float d = (p_distance / unit_size);
+ d *= d;
+ att = Math::linear2db(1.0 / (d + 0.00001));
+ } break;
+ case ATTENUATION_LOGARITHMIC: {
+ att = -20 * Math::log(p_distance / unit_size + 000001);
+ } break;
+ }
+
+ att += unit_db;
+ if (att > max_db) {
+ att = max_db;
+ }
+
+ return att;
+}
+
+void _update_sound() {
+}
+
+void AudioStreamPlayer3D::_notification(int p_what) {
+
+ if (p_what == NOTIFICATION_ENTER_TREE) {
+
+ velocity_tracker->reset(get_global_transform().origin);
+ AudioServer::get_singleton()->add_callback(_mix_audios, this);
+ if (autoplay && !get_tree()->is_editor_hint()) {
+ play();
+ }
+ }
+
+ if (p_what == NOTIFICATION_EXIT_TREE) {
+
+ AudioServer::get_singleton()->remove_callback(_mix_audios, this);
+ }
+ if (p_what == NOTIFICATION_TRANSFORM_CHANGED) {
+
+ if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {
+ velocity_tracker->update_position(get_global_transform().origin);
+ }
+ }
+
+ if (p_what == NOTIFICATION_INTERNAL_FIXED_PROCESS) {
+
+ //update anything related to position first, if possible of course
+
+ if (!output_ready) {
+
+ Vector3 linear_velocity;
+
+ //compute linear velocity for doppler
+ if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {
+ linear_velocity = velocity_tracker->get_tracked_linear_velocity();
+ }
+
+ Ref<World> world = get_world();
+ ERR_FAIL_COND(world.is_null());
+
+ int new_output_count = 0;
+
+ Vector3 global_pos = get_global_transform().origin;
+
+ int bus_index = AudioServer::get_singleton()->thread_find_bus_index(bus);
+
+ //check if any area is diverting sound into a bus
+
+ PhysicsDirectSpaceState *space_state = PhysicsServer::get_singleton()->space_get_direct_state(world->get_space());
+
+ PhysicsDirectSpaceState::ShapeResult sr[MAX_INTERSECT_AREAS];
+
+ int areas = space_state->intersect_point(global_pos, sr, MAX_INTERSECT_AREAS, Set<RID>(), area_mask, PhysicsDirectSpaceState::TYPE_MASK_AREA);
+ Area *area = NULL;
+
+ for (int i = 0; i < areas; i++) {
+ if (!sr[i].collider)
+ continue;
+
+ Area *tarea = sr[i].collider->cast_to<Area>();
+ if (!tarea)
+ continue;
+
+ if (!tarea->is_overriding_audio_bus() && !tarea->is_using_reverb_bus())
+ continue;
+
+ area = tarea;
+ break;
+ }
+
+ List<Camera *> cameras;
+ world->get_camera_list(&cameras);
+
+ for (List<Camera *>::Element *E = cameras.front(); E; E = E->next()) {
+
+ Camera *camera = E->get();
+ Viewport *vp = camera->get_viewport();
+ if (!vp->is_audio_listener())
+ continue;
+
+ Vector3 local_pos = camera->get_global_transform().orthonormalized().affine_inverse().xform(global_pos);
+
+ float dist = local_pos.length();
+
+ Vector3 area_sound_pos;
+ Vector3 cam_area_pos;
+
+ if (area && area->is_using_reverb_bus() && area->get_reverb_uniformity() > 0) {
+ area_sound_pos = space_state->get_closest_point_to_object_volume(area->get_rid(), camera->get_global_transform().origin);
+ cam_area_pos = camera->get_global_transform().affine_inverse().xform(area_sound_pos);
+ }
+
+ if (max_distance > 0) {
+
+ float total_max = max_distance;
+
+ if (area && area->is_using_reverb_bus() && area->get_reverb_uniformity() > 0) {
+ total_max = MAX(total_max, cam_area_pos.length());
+ }
+ if (total_max > max_distance) {
+ continue; //cant hear this sound in this camera
+ }
+ }
+
+ float multiplier = Math::db2linear(_get_attenuation_db(dist));
+ if (max_distance > 0) {
+ multiplier *= MAX(0, 1.0 - (dist / max_distance));
+ }
+
+ Output output;
+ output.bus_index = bus_index;
+ output.reverb_bus_index = -1; //no reverb by default
+ output.viewport = vp;
+
+ float db_att = (1.0 - MIN(1.0, multiplier)) * attenuation_filter_db;
+
+ if (emission_angle_enabled) {
+ Vector3 camtopos = global_pos - camera->get_global_transform().origin;
+ float c = camtopos.normalized().dot(get_global_transform().basis.get_axis(2).normalized()); //it's z negative
+ float angle = Math::rad2deg(Math::acos(c));
+ if (angle > emission_angle)
+ db_att -= -emission_angle_filter_attenuation_db;
+ }
+
+ output.filter_gain = Math::db2linear(db_att);
+
+ Vector3 flat_pos = local_pos;
+ flat_pos.y = 0;
+ flat_pos.normalize();
+
+ switch (AudioServer::get_singleton()->get_speaker_mode()) {
+
+ case AudioServer::SPEAKER_MODE_STEREO: {
+
+ float c = flat_pos.x * 0.5 + 0.5;
+ output.vol[0].l = 1.0 - c;
+ output.vol[0].r = c;
+
+ output.vol[0] *= multiplier;
+
+ } break;
+ case AudioServer::SPEAKER_SURROUND_51: {
+
+ float xl = Vector3(-1, 0, -1).normalized().dot(flat_pos) * 0.5 + 0.5;
+ float xr = Vector3(1, 0, -1).normalized().dot(flat_pos) * 0.5 + 0.5;
+
+ output.vol[0].l = xl;
+ output.vol[1].r = 1.0 - xl;
+ output.vol[0].r = xr;
+ output.vol[1].l = 1.0 - xr;
+
+ output.vol[0] *= multiplier;
+ output.vol[1] *= multiplier;
+ } break;
+ case AudioServer::SPEAKER_SURROUND_71: {
+
+ float xl = Vector3(-1, 0, -1).normalized().dot(flat_pos) * 0.5 + 0.5;
+ float xr = Vector3(1, 0, -1).normalized().dot(flat_pos) * 0.5 + 0.5;
+
+ output.vol[0].l = xl;
+ output.vol[1].r = 1.0 - xl;
+ output.vol[0].r = xr;
+ output.vol[1].l = 1.0 - xr;
+
+ float c = flat_pos.x * 0.5 + 0.5;
+ output.vol[2].l = 1.0 - c;
+ output.vol[2].r = c;
+
+ output.vol[0] *= multiplier;
+ output.vol[1] *= multiplier;
+ output.vol[2] *= multiplier;
+
+ } break;
+ }
+
+ bool filled_reverb = false;
+ int vol_index_max = AudioServer::get_singleton()->get_speaker_mode() + 1;
+
+ if (area) {
+
+ if (area->is_overriding_audio_bus()) {
+ //override audio bus
+ StringName bus_name = area->get_audio_bus();
+ output.bus_index = AudioServer::get_singleton()->thread_find_bus_index(bus_name);
+ }
+
+ if (area->is_using_reverb_bus()) {
+
+ filled_reverb = true;
+ StringName bus_name = area->get_reverb_bus();
+ output.reverb_bus_index = AudioServer::get_singleton()->thread_find_bus_index(bus_name);
+
+ float uniformity = area->get_reverb_uniformity();
+ float area_send = area->get_reverb_amount();
+
+ if (uniformity > 0.0) {
+
+ float distance = cam_area_pos.length();
+ float attenuation = Math::db2linear(_get_attenuation_db(distance));
+
+ //float dist_att_db = -20 * Math::log(dist + 0.00001); //logarithmic attenuation, like in real life
+
+ float center_val[3] = { 0.5, 0.25, 0.16666 };
+ AudioFrame center_frame(center_val[vol_index_max - 1], center_val[vol_index_max - 1]);
+
+ if (attenuation < 1.0) {
+ //pan the uniform sound
+ Vector3 rev_pos = cam_area_pos;
+ rev_pos.y = 0;
+ rev_pos.normalize();
+
+ switch (AudioServer::get_singleton()->get_speaker_mode()) {
+
+ case AudioServer::SPEAKER_MODE_STEREO: {
+
+ float c = rev_pos.x * 0.5 + 0.5;
+ output.reverb_vol[0].l = 1.0 - c;
+ output.reverb_vol[0].r = c;
+
+ } break;
+ case AudioServer::SPEAKER_SURROUND_51: {
+
+ float xl = Vector3(-1, 0, -1).normalized().dot(rev_pos) * 0.5 + 0.5;
+ float xr = Vector3(1, 0, -1).normalized().dot(rev_pos) * 0.5 + 0.5;
+
+ output.reverb_vol[0].l = xl;
+ output.reverb_vol[1].r = 1.0 - xl;
+ output.reverb_vol[0].r = xr;
+ output.reverb_vol[1].l = 1.0 - xr;
+
+ } break;
+ case AudioServer::SPEAKER_SURROUND_71: {
+
+ float xl = Vector3(-1, 0, -1).normalized().dot(rev_pos) * 0.5 + 0.5;
+ float xr = Vector3(1, 0, -1).normalized().dot(rev_pos) * 0.5 + 0.5;
+
+ output.reverb_vol[0].l = xl;
+ output.reverb_vol[1].r = 1.0 - xl;
+ output.reverb_vol[0].r = xr;
+ output.reverb_vol[1].l = 1.0 - xr;
+
+ float c = rev_pos.x * 0.5 + 0.5;
+ output.reverb_vol[2].l = 1.0 - c;
+ output.reverb_vol[2].r = c;
+
+ } break;
+ }
+
+ for (int i = 0; i < vol_index_max; i++) {
+
+ output.reverb_vol[i] = output.reverb_vol[i].linear_interpolate(center_frame, attenuation);
+ }
+ } else {
+ for (int i = 0; i < vol_index_max; i++) {
+
+ output.reverb_vol[i] = center_frame;
+ }
+ }
+
+ for (int i = 0; i < vol_index_max; i++) {
+
+ output.reverb_vol[i] = output.vol[i].linear_interpolate(output.reverb_vol[i] * attenuation, uniformity);
+ output.reverb_vol[i] *= area_send;
+ }
+
+ } else {
+
+ for (int i = 0; i < vol_index_max; i++) {
+
+ output.reverb_vol[i] = output.vol[i] * area_send;
+ }
+ }
+ }
+ }
+
+ if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {
+
+ Vector3 camera_velocity = camera->get_doppler_tracked_velocity();
+
+ Vector3 local_velocity = camera->get_global_transform().orthonormalized().basis.xform_inv(linear_velocity - camera_velocity);
+
+ if (local_velocity == Vector3()) {
+ output.pitch_scale = 1.0;
+ } else {
+ float approaching = local_pos.normalized().dot(local_velocity.normalized());
+ float velocity = local_velocity.length();
+ float speed_of_sound = 343.0;
+
+ output.pitch_scale = speed_of_sound / (speed_of_sound + velocity * approaching);
+ output.pitch_scale = CLAMP(output.pitch_scale, (1 / 8.0), 8.0); //avoid crazy stuff
+ }
+
+ } else {
+ output.pitch_scale = 1.0;
+ }
+
+ if (!filled_reverb) {
+
+ for (int i = 0; i < vol_index_max; i++) {
+
+ output.reverb_vol[i] = AudioFrame(0, 0);
+ }
+ }
+
+ outputs[new_output_count] = output;
+ new_output_count++;
+ if (new_output_count == MAX_OUTPUTS)
+ break;
+ }
+
+ output_count = new_output_count;
+ output_ready = true;
+ }
+
+ //start playing if requested
+ if (setplay >= 0.0) {
+ setseek = setplay;
+ active = true;
+ setplay = -1;
+ _change_notify("playing"); //update property in editor
+ }
+
+ //stop playing if no longer active
+ if (!active) {
+ set_fixed_process_internal(false);
+ _change_notify("playing"); //update property in editor
+ }
+ }
+}
+
+void AudioStreamPlayer3D::set_stream(Ref<AudioStream> p_stream) {
+
+ ERR_FAIL_COND(!p_stream.is_valid());
+ AudioServer::get_singleton()->lock();
+
+ mix_buffer.resize(AudioServer::get_singleton()->thread_get_mix_buffer_size());
+
+ if (stream_playback.is_valid()) {
+ stream_playback.unref();
+ stream.unref();
+ active = false;
+ setseek = -1;
+ }
+
+ stream = p_stream;
+ stream_playback = p_stream->instance_playback();
+
+ if (stream_playback.is_null()) {
+ stream.unref();
+ ERR_FAIL_COND(stream_playback.is_null());
+ }
+
+ AudioServer::get_singleton()->unlock();
+}
+
+Ref<AudioStream> AudioStreamPlayer3D::get_stream() const {
+
+ return stream;
+}
+
+void AudioStreamPlayer3D::set_unit_db(float p_volume) {
+
+ unit_db = p_volume;
+}
+float AudioStreamPlayer3D::get_unit_db() const {
+
+ return unit_db;
+}
+
+void AudioStreamPlayer3D::set_unit_size(float p_volume) {
+
+ unit_size = p_volume;
+}
+float AudioStreamPlayer3D::get_unit_size() const {
+
+ return unit_size;
+}
+
+void AudioStreamPlayer3D::set_max_db(float p_boost) {
+
+ max_db = p_boost;
+}
+float AudioStreamPlayer3D::get_max_db() const {
+
+ return max_db;
+}
+
+void AudioStreamPlayer3D::play(float p_from_pos) {
+
+ if (stream_playback.is_valid()) {
+ setplay = p_from_pos;
+ output_ready = false;
+ set_fixed_process_internal(true);
+ }
+}
+
+void AudioStreamPlayer3D::seek(float p_seconds) {
+
+ if (stream_playback.is_valid()) {
+ setseek = p_seconds;
+ }
+}
+
+void AudioStreamPlayer3D::stop() {
+
+ if (stream_playback.is_valid()) {
+ active = false;
+ set_fixed_process_internal(false);
+ setplay = -1;
+ }
+}
+
+bool AudioStreamPlayer3D::is_playing() const {
+
+ if (stream_playback.is_valid()) {
+ return active; // && stream_playback->is_playing();
+ }
+
+ return false;
+}
+
+float AudioStreamPlayer3D::get_pos() {
+
+ if (stream_playback.is_valid()) {
+ return stream_playback->get_pos();
+ }
+
+ return 0;
+}
+
+void AudioStreamPlayer3D::set_bus(const StringName &p_bus) {
+
+ //if audio is active, must lock this
+ AudioServer::get_singleton()->lock();
+ bus = p_bus;
+ AudioServer::get_singleton()->unlock();
+}
+StringName AudioStreamPlayer3D::get_bus() const {
+
+ for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
+ if (AudioServer::get_singleton()->get_bus_name(i) == bus) {
+ return bus;
+ }
+ }
+ return "Master";
+}
+
+void AudioStreamPlayer3D::set_autoplay(bool p_enable) {
+
+ autoplay = p_enable;
+}
+bool AudioStreamPlayer3D::is_autoplay_enabled() {
+
+ return autoplay;
+}
+
+void AudioStreamPlayer3D::_set_playing(bool p_enable) {
+
+ if (p_enable)
+ play();
+ else
+ stop();
+}
+bool AudioStreamPlayer3D::_is_active() const {
+
+ return active;
+}
+
+void AudioStreamPlayer3D::_validate_property(PropertyInfo &property) const {
+
+ if (property.name == "bus") {
+
+ String options;
+ for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
+ if (i > 0)
+ options += ",";
+ String name = AudioServer::get_singleton()->get_bus_name(i);
+ options += name;
+ }
+
+ property.hint_string = options;
+ }
+}
+
+void AudioStreamPlayer3D::_bus_layout_changed() {
+
+ _change_notify();
+}
+
+void AudioStreamPlayer3D::set_max_distance(float p_metres) {
+
+ ERR_FAIL_COND(p_metres < 0.0);
+ max_distance = p_metres;
+}
+
+float AudioStreamPlayer3D::get_max_distance() const {
+
+ return max_distance;
+}
+
+void AudioStreamPlayer3D::set_area_mask(uint32_t p_mask) {
+
+ area_mask = p_mask;
+}
+
+uint32_t AudioStreamPlayer3D::get_area_mask() const {
+
+ return area_mask;
+}
+
+void AudioStreamPlayer3D::set_emission_angle_enabled(bool p_enable) {
+ emission_angle_enabled = p_enable;
+ update_gizmo();
+}
+
+bool AudioStreamPlayer3D::is_emission_angle_enabled() const {
+ return emission_angle_enabled;
+}
+
+void AudioStreamPlayer3D::set_emission_angle(float p_angle) {
+ ERR_FAIL_COND(p_angle < 0 || p_angle > 90);
+ emission_angle = p_angle;
+ update_gizmo();
+}
+
+float AudioStreamPlayer3D::get_emission_angle() const {
+ return emission_angle;
+}
+
+void AudioStreamPlayer3D::set_emission_angle_filter_attenuation_db(float p_angle_attenuation_db) {
+
+ emission_angle_filter_attenuation_db = p_angle_attenuation_db;
+}
+
+float AudioStreamPlayer3D::get_emission_angle_filter_attenuation_db() const {
+
+ return emission_angle_filter_attenuation_db;
+}
+
+void AudioStreamPlayer3D::set_attenuation_filter_cutoff_hz(float p_hz) {
+
+ attenuation_filter_cutoff_hz = p_hz;
+}
+float AudioStreamPlayer3D::get_attenuation_filter_cutoff_hz() const {
+
+ return attenuation_filter_cutoff_hz;
+}
+
+void AudioStreamPlayer3D::set_attenuation_filter_db(float p_db) {
+
+ attenuation_filter_db = p_db;
+}
+float AudioStreamPlayer3D::get_attenuation_filter_db() const {
+
+ return attenuation_filter_db;
+}
+
+void AudioStreamPlayer3D::set_attenuation_model(AttenuationModel p_model) {
+ ERR_FAIL_INDEX(p_model, 3);
+ attenuation_model = p_model;
+}
+
+AudioStreamPlayer3D::AttenuationModel AudioStreamPlayer3D::get_attenuation_model() const {
+ return attenuation_model;
+}
+
+void AudioStreamPlayer3D::set_out_of_range_mode(OutOfRangeMode p_mode) {
+
+ ERR_FAIL_INDEX(p_mode, 2);
+ out_of_range_mode = p_mode;
+}
+
+AudioStreamPlayer3D::OutOfRangeMode AudioStreamPlayer3D::get_out_of_range_mode() const {
+
+ return out_of_range_mode;
+}
+
+void AudioStreamPlayer3D::set_doppler_tracking(DopplerTracking p_tracking) {
+
+ if (doppler_tracking == p_tracking)
+ return;
+
+ doppler_tracking = p_tracking;
+
+ if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {
+ set_notify_transform(true);
+ velocity_tracker->set_track_fixed_step(doppler_tracking == DOPPLER_TRACKING_FIXED_STEP);
+ velocity_tracker->reset(get_global_transform().origin);
+ } else {
+ set_notify_transform(false);
+ }
+}
+
+AudioStreamPlayer3D::DopplerTracking AudioStreamPlayer3D::get_doppler_tracking() const {
+
+ return doppler_tracking;
+}
+
+void AudioStreamPlayer3D::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_stream", "stream:AudioStream"), &AudioStreamPlayer3D::set_stream);
+ ClassDB::bind_method(D_METHOD("get_stream"), &AudioStreamPlayer3D::get_stream);
+
+ ClassDB::bind_method(D_METHOD("set_unit_db", "unit_db"), &AudioStreamPlayer3D::set_unit_db);
+ ClassDB::bind_method(D_METHOD("get_unit_db"), &AudioStreamPlayer3D::get_unit_db);
+
+ ClassDB::bind_method(D_METHOD("set_unit_size", "unit_size"), &AudioStreamPlayer3D::set_unit_size);
+ ClassDB::bind_method(D_METHOD("get_unit_size"), &AudioStreamPlayer3D::get_unit_size);
+
+ ClassDB::bind_method(D_METHOD("set_max_db", "max_db"), &AudioStreamPlayer3D::set_max_db);
+ ClassDB::bind_method(D_METHOD("get_max_db"), &AudioStreamPlayer3D::get_max_db);
+
+ ClassDB::bind_method(D_METHOD("play", "from_pos"), &AudioStreamPlayer3D::play, DEFVAL(0.0));
+ ClassDB::bind_method(D_METHOD("seek", "to_pos"), &AudioStreamPlayer3D::seek);
+ ClassDB::bind_method(D_METHOD("stop"), &AudioStreamPlayer3D::stop);
+
+ ClassDB::bind_method(D_METHOD("is_playing"), &AudioStreamPlayer3D::is_playing);
+ ClassDB::bind_method(D_METHOD("get_pos"), &AudioStreamPlayer3D::get_pos);
+
+ ClassDB::bind_method(D_METHOD("set_bus", "bus"), &AudioStreamPlayer3D::set_bus);
+ ClassDB::bind_method(D_METHOD("get_bus"), &AudioStreamPlayer3D::get_bus);
+
+ ClassDB::bind_method(D_METHOD("set_autoplay", "enable"), &AudioStreamPlayer3D::set_autoplay);
+ ClassDB::bind_method(D_METHOD("is_autoplay_enabled"), &AudioStreamPlayer3D::is_autoplay_enabled);
+
+ ClassDB::bind_method(D_METHOD("_set_playing", "enable"), &AudioStreamPlayer3D::_set_playing);
+ ClassDB::bind_method(D_METHOD("_is_active"), &AudioStreamPlayer3D::_is_active);
+
+ ClassDB::bind_method(D_METHOD("set_max_distance", "metres"), &AudioStreamPlayer3D::set_max_distance);
+ ClassDB::bind_method(D_METHOD("get_max_distance"), &AudioStreamPlayer3D::get_max_distance);
+
+ ClassDB::bind_method(D_METHOD("set_area_mask", "mask"), &AudioStreamPlayer3D::set_area_mask);
+ ClassDB::bind_method(D_METHOD("get_area_mask"), &AudioStreamPlayer3D::get_area_mask);
+
+ ClassDB::bind_method(D_METHOD("set_emission_angle", "degrees"), &AudioStreamPlayer3D::set_emission_angle);
+ ClassDB::bind_method(D_METHOD("get_emission_angle"), &AudioStreamPlayer3D::get_emission_angle);
+
+ ClassDB::bind_method(D_METHOD("set_emission_angle_enabled", "enabled"), &AudioStreamPlayer3D::set_emission_angle_enabled);
+ ClassDB::bind_method(D_METHOD("is_emission_angle_enabled"), &AudioStreamPlayer3D::is_emission_angle_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_emission_angle_filter_attenuation_db", "db"), &AudioStreamPlayer3D::set_emission_angle_filter_attenuation_db);
+ ClassDB::bind_method(D_METHOD("get_emission_angle_filter_attenuation_db"), &AudioStreamPlayer3D::get_emission_angle_filter_attenuation_db);
+
+ ClassDB::bind_method(D_METHOD("set_attenuation_filter_cutoff_hz", "degrees"), &AudioStreamPlayer3D::set_attenuation_filter_cutoff_hz);
+ ClassDB::bind_method(D_METHOD("get_attenuation_filter_cutoff_hz"), &AudioStreamPlayer3D::get_attenuation_filter_cutoff_hz);
+
+ ClassDB::bind_method(D_METHOD("set_attenuation_filter_db", "db"), &AudioStreamPlayer3D::set_attenuation_filter_db);
+ ClassDB::bind_method(D_METHOD("get_attenuation_filter_db"), &AudioStreamPlayer3D::get_attenuation_filter_db);
+
+ ClassDB::bind_method(D_METHOD("set_attenuation_model", "model"), &AudioStreamPlayer3D::set_attenuation_model);
+ ClassDB::bind_method(D_METHOD("get_attenuation_model"), &AudioStreamPlayer3D::get_attenuation_model);
+
+ ClassDB::bind_method(D_METHOD("set_out_of_range_mode", "mode"), &AudioStreamPlayer3D::set_out_of_range_mode);
+ ClassDB::bind_method(D_METHOD("get_out_of_range_mode"), &AudioStreamPlayer3D::get_out_of_range_mode);
+
+ ClassDB::bind_method(D_METHOD("set_doppler_tracking", "mode"), &AudioStreamPlayer3D::set_doppler_tracking);
+ ClassDB::bind_method(D_METHOD("get_doppler_tracking"), &AudioStreamPlayer3D::get_doppler_tracking);
+
+ ClassDB::bind_method(D_METHOD("_bus_layout_changed"), &AudioStreamPlayer3D::_bus_layout_changed);
+
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_stream", "get_stream");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "attenuation_model", PROPERTY_HINT_ENUM, "Inverse,InverseSquare,Log"), "set_attenuation_model", "get_attenuation_model");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_db", PROPERTY_HINT_RANGE, "-80,80"), "set_unit_db", "get_unit_db");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_size", PROPERTY_HINT_RANGE, "0.1,100,0.1"), "set_unit_size", "get_unit_size");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_db", PROPERTY_HINT_RANGE, "-24,6"), "set_max_db", "get_max_db");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_playing", "_is_active");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "is_autoplay_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_distance", PROPERTY_HINT_RANGE, "0,65536,1"), "set_max_distance", "get_max_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "out_of_range_mode", PROPERTY_HINT_ENUM, "Mix,Pause"), "set_out_of_range_mode", "get_out_of_range_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "bus", PROPERTY_HINT_ENUM, ""), "set_bus", "get_bus");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "area_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_area_mask", "get_area_mask");
+ ADD_GROUP("Emission Angle", "emission_angle");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emission_angle_enabled"), "set_emission_angle_enabled", "is_emission_angle_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_angle_degrees", PROPERTY_HINT_RANGE, "0.1,90,0.1"), "set_emission_angle", "get_emission_angle");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_angle_filter_attenuation_db", PROPERTY_HINT_RANGE, "-80,0,0.1"), "set_emission_angle_filter_attenuation_db", "get_emission_angle_filter_attenuation_db");
+ ADD_GROUP("Attenuation Filter", "attenuation_filter_");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "attenuation_filter_cutoff_hz", PROPERTY_HINT_RANGE, "50,50000,1"), "set_attenuation_filter_cutoff_hz", "get_attenuation_filter_cutoff_hz");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "attenuation_filter_db", PROPERTY_HINT_RANGE, "-80,0,0.1"), "set_attenuation_filter_db", "get_attenuation_filter_db");
+ ADD_GROUP("Doppler", "doppler_");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "doppler_tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Fixed"), "set_doppler_tracking", "get_doppler_tracking");
+
+ BIND_CONSTANT(ATTENUATION_INVERSE_DISTANCE);
+ BIND_CONSTANT(ATTENUATION_INVERSE_SQUARE_DISTANCE);
+ BIND_CONSTANT(ATTENUATION_LOGARITHMIC);
+
+ BIND_CONSTANT(OUT_OF_RANGE_MIX);
+ BIND_CONSTANT(OUT_OF_RANGE_PAUSE);
+
+ BIND_CONSTANT(DOPPLER_TRACKING_DISABLED);
+ BIND_CONSTANT(DOPPLER_TRACKING_IDLE_STEP);
+ BIND_CONSTANT(DOPPLER_TRACKING_FIXED_STEP);
+}
+
+AudioStreamPlayer3D::AudioStreamPlayer3D() {
+
+ unit_db = 0;
+ unit_size = 1;
+ attenuation_model = ATTENUATION_INVERSE_DISTANCE;
+ max_db = 3;
+ autoplay = false;
+ setseek = -1;
+ active = false;
+ output_count = 0;
+ prev_output_count = 0;
+ max_distance = 0;
+ setplay = -1;
+ output_ready = false;
+ area_mask = 1;
+ emission_angle = 45;
+ emission_angle_enabled = false;
+ emission_angle_filter_attenuation_db = -12;
+ attenuation_filter_cutoff_hz = 5000;
+ attenuation_filter_db = -24;
+ out_of_range_mode = OUT_OF_RANGE_MIX;
+ doppler_tracking = DOPPLER_TRACKING_DISABLED;
+
+ velocity_tracker.instance();
+ AudioServer::get_singleton()->connect("bus_layout_changed", this, "_bus_layout_changed");
+}
+AudioStreamPlayer3D::~AudioStreamPlayer3D() {
+}
diff --git a/scene/3d/audio_stream_player_3d.h b/scene/3d/audio_stream_player_3d.h
new file mode 100644
index 0000000000..8603cab5a4
--- /dev/null
+++ b/scene/3d/audio_stream_player_3d.h
@@ -0,0 +1,175 @@
+#ifndef AUDIO_STREAM_PLAYER_3D_H
+#define AUDIO_STREAM_PLAYER_3D_H
+
+#include "scene/3d/spatial.h"
+#include "scene/3d/spatial_velocity_tracker.h"
+#include "servers/audio/audio_filter_sw.h"
+#include "servers/audio/audio_stream.h"
+#include "servers/audio_server.h"
+
+class Camera;
+class AudioStreamPlayer3D : public Spatial {
+
+ GDCLASS(AudioStreamPlayer3D, Spatial)
+public:
+ enum AttenuationModel {
+ ATTENUATION_INVERSE_DISTANCE,
+ ATTENUATION_INVERSE_SQUARE_DISTANCE,
+ ATTENUATION_LOGARITHMIC,
+ };
+
+ enum OutOfRangeMode {
+ OUT_OF_RANGE_MIX,
+ OUT_OF_RANGE_PAUSE,
+ };
+
+ enum DopplerTracking {
+ DOPPLER_TRACKING_DISABLED,
+ DOPPLER_TRACKING_IDLE_STEP,
+ DOPPLER_TRACKING_FIXED_STEP
+ };
+
+private:
+ enum {
+ MAX_OUTPUTS = 8,
+ MAX_INTERSECT_AREAS = 32
+
+ };
+
+ struct Output {
+
+ AudioFilterSW filter;
+ AudioFilterSW::Processor filter_process[6];
+ AudioFrame vol[3];
+ float filter_gain;
+ float pitch_scale;
+ int bus_index;
+ int reverb_bus_index;
+ AudioFrame reverb_vol[3];
+ Viewport *viewport; //pointer only used for reference to previous mix
+
+ Output() {
+ filter_gain = 0;
+ viewport = NULL;
+ reverb_bus_index = -1;
+ bus_index = -1;
+ }
+ };
+
+ Output outputs[MAX_OUTPUTS];
+ volatile int output_count;
+ volatile bool output_ready;
+
+ //these are used by audio thread to have a reference of previous volumes (for ramping volume and avoiding clicks)
+ Output prev_outputs[MAX_OUTPUTS];
+ int prev_output_count;
+
+ Ref<AudioStreamPlayback> stream_playback;
+ Ref<AudioStream> stream;
+ Vector<AudioFrame> mix_buffer;
+
+ volatile float setseek;
+ volatile bool active;
+ volatile float setplay;
+
+ AttenuationModel attenuation_model;
+ float unit_db;
+ float unit_size;
+ float max_db;
+ bool autoplay;
+ StringName bus;
+
+ void _mix_audio();
+ static void _mix_audios(void *self) { reinterpret_cast<AudioStreamPlayer3D *>(self)->_mix_audio(); }
+
+ void _set_playing(bool p_enable);
+ bool _is_active() const;
+
+ void _bus_layout_changed();
+
+ uint32_t area_mask;
+
+ bool emission_angle_enabled;
+ float emission_angle;
+ float emission_angle_filter_attenuation_db;
+ float attenuation_filter_cutoff_hz;
+ float attenuation_filter_db;
+
+ float max_distance;
+
+ Ref<SpatialVelocityTracker> velocity_tracker;
+
+ DopplerTracking doppler_tracking;
+
+ OutOfRangeMode out_of_range_mode;
+
+ float _get_attenuation_db(float p_distance) const;
+
+protected:
+ void _validate_property(PropertyInfo &property) const;
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ void set_stream(Ref<AudioStream> p_stream);
+ Ref<AudioStream> get_stream() const;
+
+ void set_unit_db(float p_volume);
+ float get_unit_db() const;
+
+ void set_unit_size(float p_volume);
+ float get_unit_size() const;
+
+ void set_max_db(float p_boost);
+ float get_max_db() const;
+
+ void play(float p_from_pos = 0.0);
+ void seek(float p_seconds);
+ void stop();
+ bool is_playing() const;
+ float get_pos();
+
+ void set_bus(const StringName &p_bus);
+ StringName get_bus() const;
+
+ void set_autoplay(bool p_enable);
+ bool is_autoplay_enabled();
+
+ void set_max_distance(float p_metres);
+ float get_max_distance() const;
+
+ void set_area_mask(uint32_t p_mask);
+ uint32_t get_area_mask() const;
+
+ void set_emission_angle_enabled(bool p_enable);
+ bool is_emission_angle_enabled() const;
+
+ void set_emission_angle(float p_angle);
+ float get_emission_angle() const;
+
+ void set_emission_angle_filter_attenuation_db(float p_angle_attenuation_db);
+ float get_emission_angle_filter_attenuation_db() const;
+
+ void set_attenuation_filter_cutoff_hz(float p_hz);
+ float get_attenuation_filter_cutoff_hz() const;
+
+ void set_attenuation_filter_db(float p_db);
+ float get_attenuation_filter_db() const;
+
+ void set_attenuation_model(AttenuationModel p_model);
+ AttenuationModel get_attenuation_model() const;
+
+ void set_out_of_range_mode(OutOfRangeMode p_mode);
+ OutOfRangeMode get_out_of_range_mode() const;
+
+ void set_doppler_tracking(DopplerTracking p_tracking);
+ DopplerTracking get_doppler_tracking() const;
+
+ AudioStreamPlayer3D();
+ ~AudioStreamPlayer3D();
+};
+
+VARIANT_ENUM_CAST(AudioStreamPlayer3D::AttenuationModel)
+VARIANT_ENUM_CAST(AudioStreamPlayer3D::OutOfRangeMode)
+VARIANT_ENUM_CAST(AudioStreamPlayer3D::DopplerTracking)
+#endif // AUDIO_STREAM_PLAYER_3D_H
diff --git a/scene/3d/body_shape.cpp b/scene/3d/body_shape.cpp
deleted file mode 100644
index 68f166c5b9..0000000000
--- a/scene/3d/body_shape.cpp
+++ /dev/null
@@ -1,920 +0,0 @@
-/*************************************************************************/
-/* body_shape.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2017 Godot Engine contributors (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 "body_shape.h"
-#include "scene/resources/box_shape.h"
-#include "scene/resources/capsule_shape.h"
-#include "scene/resources/concave_polygon_shape.h"
-#include "scene/resources/convex_polygon_shape.h"
-#include "scene/resources/plane_shape.h"
-#include "scene/resources/ray_shape.h"
-#include "scene/resources/sphere_shape.h"
-#include "servers/visual_server.h"
-//TODO: Implement CylinderShape and HeightMapShape?
-#include "mesh_instance.h"
-#include "physics_body.h"
-#include "quick_hull.h"
-
-void CollisionShape::_update_body() {
-
- if (!is_inside_tree() || !can_update_body)
- return;
- if (!get_tree()->is_editor_hint())
- return;
- if (get_parent() && get_parent()->cast_to<CollisionObject>())
- get_parent()->cast_to<CollisionObject>()->_update_shapes_from_children();
-}
-
-void CollisionShape::make_convex_from_brothers() {
-
- Node *p = get_parent();
- if (!p)
- return;
-
- for (int i = 0; i < p->get_child_count(); i++) {
-
- Node *n = p->get_child(i);
- if (n->cast_to<MeshInstance>()) {
-
- MeshInstance *mi = n->cast_to<MeshInstance>();
- Ref<Mesh> m = mi->get_mesh();
- if (m.is_valid()) {
-
- Ref<Shape> s = m->create_convex_shape();
- set_shape(s);
- }
- }
- }
-}
-/*
-
-void CollisionShape::_update_indicator() {
-
- while (VisualServer::get_singleton()->mesh_get_surface_count(indicator))
- VisualServer::get_singleton()->mesh_remove_surface(indicator,0);
-
- if (shape.is_null())
- return;
-
- PoolVector<Vector3> points;
- PoolVector<Vector3> normals;
-
- VS::PrimitiveType pt = VS::PRIMITIVE_TRIANGLES;
-
- if (shape->cast_to<RayShape>()) {
-
- RayShape *rs = shape->cast_to<RayShape>();
- points.push_back(Vector3());
- points.push_back(Vector3(0,0,rs->get_length()));
- pt = VS::PRIMITIVE_LINES;
- } else if (shape->cast_to<SphereShape>()) {
-
- //VisualServer *vs=VisualServer::get_singleton();
- SphereShape *shapeptr=shape->cast_to<SphereShape>();
-
-
- Color col(0.4,1.0,1.0,0.5);
-
- int lats=6;
- int lons=12;
- float size=shapeptr->get_radius();
-
-
- for(int i = 1; i <= lats; i++) {
- double lat0 = Math_PI * (-0.5 + (double) (i - 1) / lats);
- double z0 = Math::sin(lat0);
- double zr0 = Math::cos(lat0);
-
- double lat1 = Math_PI * (-0.5 + (double) i / lats);
- double z1 = Math::sin(lat1);
- double zr1 = Math::cos(lat1);
-
- for(int j = lons; j >= 1; j--) {
-
- double lng0 = 2 * Math_PI * (double) (j - 1) / lons;
- double x0 = Math::cos(lng0);
- double y0 = Math::sin(lng0);
-
- double lng1 = 2 * Math_PI * (double) (j) / lons;
- double x1 = Math::cos(lng1);
- double y1 = Math::sin(lng1);
-
- Vector3 v4=Vector3(x0 * zr0, z0, y0 *zr0)*size;
- Vector3 v3=Vector3(x0 * zr1, z1, y0 *zr1)*size;
- Vector3 v2=Vector3(x1 * zr1, z1, y1 *zr1)*size;
- Vector3 v1=Vector3(x1 * zr0, z0, y1 *zr0)*size;
-
- Vector<Vector3> line;
- line.push_back(v1);
- line.push_back(v2);
- line.push_back(v3);
- line.push_back(v4);
-
-
- points.push_back(v1);
- points.push_back(v2);
- points.push_back(v3);
-
- points.push_back(v1);
- points.push_back(v3);
- points.push_back(v4);
-
- normals.push_back(v1.normalized());
- normals.push_back(v2.normalized());
- normals.push_back(v3.normalized());
-
- normals.push_back(v1.normalized());
- normals.push_back(v3.normalized());
- normals.push_back(v4.normalized());
-
- }
- }
- } else if (shape->cast_to<BoxShape>()) {
-
- BoxShape *shapeptr=shape->cast_to<BoxShape>();
-
- for (int i=0;i<6;i++) {
-
-
- Vector3 face_points[4];
-
-
- for (int j=0;j<4;j++) {
-
- float v[3];
- v[0]=1.0;
- v[1]=1-2*((j>>1)&1);
- v[2]=v[1]*(1-2*(j&1));
-
- for (int k=0;k<3;k++) {
-
- if (i<3)
- face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1);
- else
- face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1);
- }
- }
- Vector3 normal;
- normal[i%3]=(i>=3?-1:1);
-
- for(int j=0;j<4;j++)
- face_points[j]*=shapeptr->get_extents();
-
- points.push_back(face_points[0]);
- points.push_back(face_points[1]);
- points.push_back(face_points[2]);
-
- points.push_back(face_points[0]);
- points.push_back(face_points[2]);
- points.push_back(face_points[3]);
-
- for(int n=0;n<6;n++)
- normals.push_back(normal);
-
- }
-
- } else if (shape->cast_to<ConvexPolygonShape>()) {
-
- ConvexPolygonShape *shapeptr=shape->cast_to<ConvexPolygonShape>();
-
- Geometry::MeshData md;
- QuickHull::build(Variant(shapeptr->get_points()),md);
-
- for(int i=0;i<md.faces.size();i++) {
-
- for(int j=2;j<md.faces[i].indices.size();j++) {
- points.push_back(md.vertices[md.faces[i].indices[0]]);
- points.push_back(md.vertices[md.faces[i].indices[j-1]]);
- points.push_back(md.vertices[md.faces[i].indices[j]]);
- normals.push_back(md.faces[i].plane.normal);
- normals.push_back(md.faces[i].plane.normal);
- normals.push_back(md.faces[i].plane.normal);
- }
- }
- } else if (shape->cast_to<ConcavePolygonShape>()) {
-
- ConcavePolygonShape *shapeptr=shape->cast_to<ConcavePolygonShape>();
-
- points = shapeptr->get_faces();
- for(int i=0;i<points.size()/3;i++) {
-
- Vector3 n = Plane( points[i*3+0],points[i*3+1],points[i*3+2] ).normal;
- normals.push_back(n);
- normals.push_back(n);
- normals.push_back(n);
- }
-
- } else if (shape->cast_to<CapsuleShape>()) {
-
- CapsuleShape *shapeptr=shape->cast_to<CapsuleShape>();
-
- PoolVector<Plane> planes = Geometry::build_capsule_planes(shapeptr->get_radius(), shapeptr->get_height()/2.0, 12, Vector3::AXIS_Z);
- Geometry::MeshData md = Geometry::build_convex_mesh(planes);
-
- for(int i=0;i<md.faces.size();i++) {
-
- for(int j=2;j<md.faces[i].indices.size();j++) {
- points.push_back(md.vertices[md.faces[i].indices[0]]);
- points.push_back(md.vertices[md.faces[i].indices[j-1]]);
- points.push_back(md.vertices[md.faces[i].indices[j]]);
- normals.push_back(md.faces[i].plane.normal);
- normals.push_back(md.faces[i].plane.normal);
- normals.push_back(md.faces[i].plane.normal);
-
- }
- }
-
- } else if (shape->cast_to<PlaneShape>()) {
-
- PlaneShape *shapeptr=shape->cast_to<PlaneShape>();
-
- Plane p = shapeptr->get_plane();
- Vector3 n1 = p.get_any_perpendicular_normal();
- Vector3 n2 = p.normal.cross(n1).normalized();
-
- Vector3 pface[4]={
- p.normal*p.d+n1*100.0+n2*100.0,
- p.normal*p.d+n1*100.0+n2*-100.0,
- p.normal*p.d+n1*-100.0+n2*-100.0,
- p.normal*p.d+n1*-100.0+n2*100.0,
- };
-
- points.push_back(pface[0]);
- points.push_back(pface[1]);
- points.push_back(pface[2]);
-
- points.push_back(pface[0]);
- points.push_back(pface[2]);
- points.push_back(pface[3]);
-
- normals.push_back(p.normal);
- normals.push_back(p.normal);
- normals.push_back(p.normal);
- normals.push_back(p.normal);
- normals.push_back(p.normal);
- normals.push_back(p.normal);
-
- }
-
- if (!points.size())
- return;
- RID material = VisualServer::get_singleton()->fixed_material_create();
- VisualServer::get_singleton()->fixed_material_set_param(material,VS::FIXED_MATERIAL_PARAM_DIFFUSE,Color(0,0.6,0.7,0.3));
- VisualServer::get_singleton()->fixed_material_set_param(material,VS::FIXED_MATERIAL_PARAM_EMISSION,0.7);
- if (normals.size()==0)
- VisualServer::get_singleton()->material_set_flag(material,VS::MATERIAL_FLAG_UNSHADED,true);
- VisualServer::get_singleton()->material_set_flag(material,VS::MATERIAL_FLAG_DOUBLE_SIDED,true);
- Array d;
- d.resize(VS::ARRAY_MAX);
- d[VS::ARRAY_VERTEX]=points;
- if (normals.size())
- d[VS::ARRAY_NORMAL]=normals;
- VisualServer::get_singleton()->mesh_add_surface(indicator,pt,d);
- VisualServer::get_singleton()->mesh_surface_set_material(indicator,0,material,true);
-
-}
-
-*/
-void CollisionShape::_add_to_collision_object(Object *p_cshape) {
-
- if (unparenting)
- return;
-
- CollisionObject *co = p_cshape->cast_to<CollisionObject>();
- ERR_FAIL_COND(!co);
-
- if (shape.is_valid()) {
-
- update_shape_index = co->get_shape_count();
- co->add_shape(shape, get_transform());
- if (trigger)
- co->set_shape_as_trigger(co->get_shape_count() - 1, true);
- } else {
- update_shape_index = -1;
- }
-}
-
-void CollisionShape::_notification(int p_what) {
-
- switch (p_what) {
-
- case NOTIFICATION_ENTER_TREE: {
- unparenting = false;
- can_update_body = get_tree()->is_editor_hint();
- set_notify_local_transform(!can_update_body);
-
- if (get_tree()->is_debugging_collisions_hint()) {
- _create_debug_shape();
- }
-
- //indicator_instance = VisualServer::get_singleton()->instance_create2(indicator,get_world()->get_scenario());
- } break;
- case NOTIFICATION_TRANSFORM_CHANGED: {
- //VisualServer::get_singleton()->instance_set_transform(indicator_instance,get_global_transform());
- if (can_update_body && updating_body) {
- _update_body();
- }
- } break;
- case NOTIFICATION_EXIT_TREE: {
- /* if (indicator_instance.is_valid()) {
- VisualServer::get_singleton()->free(indicator_instance);
- indicator_instance=RID();
- }*/
- can_update_body = false;
- set_notify_local_transform(false);
- if (debug_shape) {
- debug_shape->queue_delete();
- debug_shape = NULL;
- }
- } break;
- case NOTIFICATION_UNPARENTED: {
- unparenting = true;
- if (can_update_body && updating_body)
- _update_body();
- } break;
- case NOTIFICATION_PARENTED: {
- if (can_update_body && updating_body)
- _update_body();
- } break;
- case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
-
- if (!can_update_body && update_shape_index >= 0) {
-
- CollisionObject *co = get_parent()->cast_to<CollisionObject>();
- if (co) {
- co->set_shape_transform(update_shape_index, get_transform());
- }
- }
-
- } break;
- }
-}
-
-void CollisionShape::resource_changed(RES res) {
-
- update_gizmo();
-}
-
-void CollisionShape::_set_update_shape_index(int p_index) {
-
- update_shape_index = p_index;
-}
-
-int CollisionShape::_get_update_shape_index() const {
-
- return update_shape_index;
-}
-
-String CollisionShape::get_configuration_warning() const {
-
- if (!get_parent()->cast_to<CollisionObject>()) {
- return TTR("CollisionShape only serves to provide a collision shape to a CollisionObject derived node. Please only use it as a child of Area, StaticBody, RigidBody, KinematicBody, etc. to give them a shape.");
- }
-
- if (!shape.is_valid()) {
- return TTR("A shape must be provided for CollisionShape to function. Please create a shape resource for it!");
- }
-
- return String();
-}
-
-void CollisionShape::_bind_methods() {
-
- //not sure if this should do anything
- ClassDB::bind_method(D_METHOD("resource_changed", "resource"), &CollisionShape::resource_changed);
- ClassDB::bind_method(D_METHOD("set_shape", "shape"), &CollisionShape::set_shape);
- ClassDB::bind_method(D_METHOD("get_shape"), &CollisionShape::get_shape);
- ClassDB::bind_method(D_METHOD("_add_to_collision_object"), &CollisionShape::_add_to_collision_object);
- ClassDB::bind_method(D_METHOD("set_trigger", "enable"), &CollisionShape::set_trigger);
- ClassDB::bind_method(D_METHOD("is_trigger"), &CollisionShape::is_trigger);
- ClassDB::bind_method(D_METHOD("make_convex_from_brothers"), &CollisionShape::make_convex_from_brothers);
- ClassDB::set_method_flags("CollisionShape", "make_convex_from_brothers", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
- ClassDB::bind_method(D_METHOD("_set_update_shape_index", "index"), &CollisionShape::_set_update_shape_index);
- ClassDB::bind_method(D_METHOD("_get_update_shape_index"), &CollisionShape::_get_update_shape_index);
-
- ClassDB::bind_method(D_METHOD("get_collision_object_shape_index"), &CollisionShape::get_collision_object_shape_index);
-
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape"), "set_shape", "get_shape");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "trigger"), "set_trigger", "is_trigger");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "_update_shape_index", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_update_shape_index", "_get_update_shape_index");
-}
-
-void CollisionShape::set_shape(const Ref<Shape> &p_shape) {
-
- if (!shape.is_null())
- shape->unregister_owner(this);
- shape = p_shape;
- if (!shape.is_null())
- shape->register_owner(this);
- update_gizmo();
- if (updating_body) {
- _update_body();
- } else if (can_update_body && update_shape_index >= 0 && is_inside_tree()) {
- CollisionObject *co = get_parent()->cast_to<CollisionObject>();
- if (co) {
- co->set_shape(update_shape_index, p_shape);
- }
- }
-}
-
-Ref<Shape> CollisionShape::get_shape() const {
-
- return shape;
-}
-
-void CollisionShape::set_updating_body(bool p_update) {
- updating_body = p_update;
-}
-
-bool CollisionShape::is_updating_body() const {
-
- return updating_body;
-}
-
-void CollisionShape::set_trigger(bool p_trigger) {
-
- trigger = p_trigger;
- if (updating_body) {
- _update_body();
- } else if (can_update_body && update_shape_index >= 0 && is_inside_tree()) {
- CollisionObject *co = get_parent()->cast_to<CollisionObject>();
- if (co) {
- co->set_shape_as_trigger(update_shape_index, p_trigger);
- }
- }
-}
-
-bool CollisionShape::is_trigger() const {
-
- return trigger;
-}
-
-CollisionShape::CollisionShape() {
-
- //indicator = VisualServer::get_singleton()->mesh_create();
- updating_body = true;
- unparenting = false;
- update_shape_index = -1;
- trigger = false;
- can_update_body = false;
- debug_shape = NULL;
-}
-
-CollisionShape::~CollisionShape() {
- if (!shape.is_null())
- shape->unregister_owner(this);
- //VisualServer::get_singleton()->free(indicator);
-}
-
-void CollisionShape::_create_debug_shape() {
-
- if (debug_shape) {
- debug_shape->queue_delete();
- debug_shape = NULL;
- }
-
- Ref<Shape> s = get_shape();
-
- if (s.is_null())
- return;
-
- Ref<Mesh> mesh = s->get_debug_mesh();
-
- MeshInstance *mi = memnew(MeshInstance);
- mi->set_mesh(mesh);
-
- add_child(mi);
- debug_shape = mi;
-}
-
-#if 0
-#include "body_volume.h"
-
-#include "geometry.h"
-#include "scene/3d/physics_body.h"
-
-#define ADD_TRIANGLE(m_a, m_b, m_c, m_color) \
- { \
- Vector<Vector3> points; \
- points.resize(3); \
- points[0] = m_a; \
- points[1] = m_b; \
- points[2] = m_c; \
- Vector<Color> colors; \
- colors.resize(3); \
- colors[0] = m_color; \
- colors[1] = m_color; \
- colors[2] = m_color; \
- vs->poly_add_primitive(p_indicator, points, Vector<Vector3>(), colors, Vector<Vector3>()); \
- }
-
-
-void CollisionShape::_notification(int p_what) {
-
- switch (p_what) {
- case NOTIFICATION_ENTER_SCENE: {
-
-
- if (get_root_node()->get_editor() && !indicator.is_valid()) {
-
- indicator=VisualServer::get_singleton()->poly_create();
- RID mat=VisualServer::get_singleton()->fixed_material_create();
- VisualServer::get_singleton()->material_set_flag( mat, VisualServer::MATERIAL_FLAG_UNSHADED, true );
- VisualServer::get_singleton()->material_set_flag( mat, VisualServer::MATERIAL_FLAG_WIREFRAME, true );
- VisualServer::get_singleton()->material_set_flag( mat, VisualServer::MATERIAL_FLAG_DOUBLE_SIDED, true );
- VisualServer::get_singleton()->material_set_line_width( mat, 3 );
-
- VisualServer::get_singleton()->poly_set_material(indicator,mat,true);
-
- update_indicator(indicator);
- }
-
- if (indicator.is_valid()) {
-
- indicator_instance=VisualServer::get_singleton()->instance_create2(indicator,get_world()->get_scenario());
- VisualServer::get_singleton()->instance_attach_object_instance_ID(indicator_instance,get_instance_ID());
- }
- volume_changed();
- } break;
- case NOTIFICATION_EXIT_SCENE: {
-
- if (indicator_instance.is_valid()) {
-
- VisualServer::get_singleton()->free(indicator_instance);
- }
- volume_changed();
- } break;
- case NOTIFICATION_TRANSFORM_CHANGED: {
-
- if (indicator_instance.is_valid()) {
-
- VisualServer::get_singleton()->instance_set_transform(indicator_instance,get_global_transform());
- }
- volume_changed();
- } break;
- default: {}
- }
-}
-
-void CollisionShape::volume_changed() {
-
- if (indicator.is_valid())
- update_indicator(indicator);
-
- Object *parent=get_parent();
- if (!parent)
- return;
- PhysicsBody *physics_body=parent->cast_to<PhysicsBody>();
-
- ERR_EXPLAIN("CollisionShape parent is not of type PhysicsBody");
- ERR_FAIL_COND(!physics_body);
-
- physics_body->recompute_child_volumes();
-
-}
-
-RID CollisionShape::_get_visual_instance_rid() const {
-
- return indicator_instance;
-
-}
-
-void CollisionShape::_bind_methods() {
-
- ClassDB::bind_method("_get_visual_instance_rid",&CollisionShape::_get_visual_instance_rid);
-}
-
-CollisionShape::CollisionShape() {
-
-}
-
-CollisionShape::~CollisionShape() {
-
- if (indicator.is_valid()) {
-
- VisualServer::get_singleton()->free(indicator);
- }
-
-}
-
-void CollisionShapeSphere::_set(const String& p_name, const Variant& p_value) {
-
- if (p_name=="radius") {
- radius=p_value;
- volume_changed();
- }
-
-}
-
-Variant CollisionShapeSphere::_get(const String& p_name) const {
-
- if (p_name=="radius") {
- return radius;
- }
-
- return Variant();
-}
-
-void CollisionShapeSphere::_get_property_list( List<PropertyInfo> *p_list) const {
-
- p_list->push_back( PropertyInfo(Variant::REAL,"radius",PROPERTY_HINT_RANGE,"0.01,16384,0.01") );
-}
-
-void CollisionShapeSphere::update_indicator(RID p_indicator) {
-
- VisualServer *vs=VisualServer::get_singleton();
-
- vs->poly_clear(p_indicator);
- Color col(0.4,1.0,1.0,0.5);
-
- int lats=6;
- int lons=12;
- float size=radius;
-
- for(int i = 1; i <= lats; i++) {
- double lat0 = Math_PI * (-0.5 + (double) (i - 1) / lats);
- double z0 = Math::sin(lat0);
- double zr0 = Math::cos(lat0);
-
- double lat1 = Math_PI * (-0.5 + (double) i / lats);
- double z1 = Math::sin(lat1);
- double zr1 = Math::cos(lat1);
-
- for(int j = lons; j >= 1; j--) {
-
- double lng0 = 2 * Math_PI * (double) (j - 1) / lons;
- double x0 = Math::cos(lng0);
- double y0 = Math::sin(lng0);
-
- double lng1 = 2 * Math_PI * (double) (j) / lons;
- double x1 = Math::cos(lng1);
- double y1 = Math::sin(lng1);
-
- Vector3 v4=Vector3(x0 * zr0, z0, y0 *zr0)*size;
- Vector3 v3=Vector3(x0 * zr1, z1, y0 *zr1)*size;
- Vector3 v2=Vector3(x1 * zr1, z1, y1 *zr1)*size;
- Vector3 v1=Vector3(x1 * zr0, z0, y1 *zr0)*size;
-
- Vector<Vector3> line;
- line.push_back(v1);
- line.push_back(v2);
- line.push_back(v3);
- line.push_back(v4);
-
- Vector<Color> cols;
- cols.push_back(col);
- cols.push_back(col);
- cols.push_back(col);
- cols.push_back(col);
-
-
- VisualServer::get_singleton()->poly_add_primitive(p_indicator,line,Vector<Vector3>(),cols,Vector<Vector3>());
- }
- }
-}
-
-void CollisionShapeSphere::append_to_volume(Ref<Shape> p_volume) {
-
- p_volume->add_sphere_shape(radius,get_transform());
-}
-
-
-CollisionShapeSphere::CollisionShapeSphere() {
-
- radius=1.0;
-}
-
-/* BOX */
-
-
-void CollisionShapeBox::_set(const String& p_name, const Variant& p_value) {
-
- if (p_name=="half_extents") {
- half_extents=p_value;
- volume_changed();
- }
-
-}
-
-Variant CollisionShapeBox::_get(const String& p_name) const {
-
- if (p_name=="half_extents") {
- return half_extents;
- }
-
- return Variant();
-}
-
-void CollisionShapeBox::_get_property_list( List<PropertyInfo> *p_list) const {
-
- p_list->push_back( PropertyInfo(Variant::VECTOR3,"half_extents" ) );
-}
-
-
-void CollisionShapeBox::update_indicator(RID p_indicator) {
-
- VisualServer *vs=VisualServer::get_singleton();
-
- vs->poly_clear(p_indicator);
- Color col(0.4,1.0,1.0,0.5);
-
-
- for (int i=0;i<6;i++) {
-
-
- Vector3 face_points[4];
-
- for (int j=0;j<4;j++) {
-
- float v[3];
- v[0]=1.0;
- v[1]=1-2*((j>>1)&1);
- v[2]=v[1]*(1-2*(j&1));
-
- for (int k=0;k<3;k++) {
-
- if (i<3)
- face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1);
- else
- face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1);
- }
- }
-
- for(int j=0;j<4;j++)
- face_points[i]*=half_extents;
-
- ADD_TRIANGLE(face_points[0],face_points[1],face_points[2],col);
- ADD_TRIANGLE(face_points[2],face_points[3],face_points[0],col);
-
- }
-}
-
-void CollisionShapeBox::append_to_volume(Ref<Shape> p_volume) {
-
- p_volume->add_box_shape(half_extents,get_transform());
-}
-
-
-CollisionShapeBox::CollisionShapeBox() {
-
- half_extents=Vector3(1,1,1);
-}
-
-/* CYLINDER */
-
-
-void CollisionShapeCylinder::_set(const String& p_name, const Variant& p_value) {
-
- if (p_name=="radius") {
- radius=p_value;
- volume_changed();
- }
- if (p_name=="height") {
- height=p_value;
- volume_changed();
- }
-
-}
-
-Variant CollisionShapeCylinder::_get(const String& p_name) const {
-
- if (p_name=="radius") {
- return radius;
- }
- if (p_name=="height") {
- return height;
- }
- return Variant();
-}
-
-void CollisionShapeCylinder::_get_property_list( List<PropertyInfo> *p_list) const {
-
- p_list->push_back( PropertyInfo(Variant::REAL,"radius",PROPERTY_HINT_RANGE,"0.01,16384,0.01") );
- p_list->push_back( PropertyInfo(Variant::REAL,"height",PROPERTY_HINT_RANGE,"0.01,16384,0.01") );
-}
-
-
-void CollisionShapeCylinder::update_indicator(RID p_indicator) {
-
- VisualServer *vs=VisualServer::get_singleton();
-
- vs->poly_clear(p_indicator);
- Color col(0.4,1.0,1.0,0.5);
-
- PoolVector<Plane> planes = Geometry::build_cylinder_planes(radius, height, 12, Vector3::AXIS_Z);
- Geometry::MeshData md = Geometry::build_convex_mesh(planes);
-
- for(int i=0;i<md.faces.size();i++) {
-
- for(int j=2;j<md.faces[i].indices.size();j++) {
- ADD_TRIANGLE(md.vertices[md.faces[i].indices[0]],md.vertices[md.faces[i].indices[j-1]],md.vertices[md.faces[i].indices[j]],col);
- }
- }
-
-}
-
-void CollisionShapeCylinder::append_to_volume(Ref<Shape> p_volume) {
-
- p_volume->add_cylinder_shape(radius,height*2.0,get_transform());
-}
-
-
-CollisionShapeCylinder::CollisionShapeCylinder() {
-
- height=1;
- radius=1;
-}
-
-/* CAPSULE */
-
-
-void CollisionShapeCapsule::_set(const String& p_name, const Variant& p_value) {
-
- if (p_name=="radius") {
- radius=p_value;
- volume_changed();
- }
-
- if (p_name=="height") {
- height=p_value;
- volume_changed();
- }
-
-}
-
-Variant CollisionShapeCapsule::_get(const String& p_name) const {
-
- if (p_name=="radius") {
- return radius;
- }
- if (p_name=="height") {
- return height;
- }
- return Variant();
-}
-
-void CollisionShapeCapsule::_get_property_list( List<PropertyInfo> *p_list) const {
-
- p_list->push_back( PropertyInfo(Variant::REAL,"radius",PROPERTY_HINT_RANGE,"0.01,16384,0.01") );
- p_list->push_back( PropertyInfo(Variant::REAL,"height",PROPERTY_HINT_RANGE,"0.01,16384,0.01") );
-}
-
-
-void CollisionShapeCapsule::update_indicator(RID p_indicator) {
-
- VisualServer *vs=VisualServer::get_singleton();
-
- vs->poly_clear(p_indicator);
- Color col(0.4,1.0,1.0,0.5);
-
- PoolVector<Plane> planes = Geometry::build_capsule_planes(radius, height, 12, 3, Vector3::AXIS_Z);
- Geometry::MeshData md = Geometry::build_convex_mesh(planes);
-
- for(int i=0;i<md.faces.size();i++) {
-
- for(int j=2;j<md.faces[i].indices.size();j++) {
- ADD_TRIANGLE(md.vertices[md.faces[i].indices[0]],md.vertices[md.faces[i].indices[j-1]],md.vertices[md.faces[i].indices[j]],col);
- }
- }
-
-}
-
-void CollisionShapeCapsule::append_to_volume(Ref<Shape> p_volume) {
-
-
- p_volume->add_capsule_shape(radius,height,get_transform());
-}
-
-
-CollisionShapeCapsule::CollisionShapeCapsule() {
-
- height=1;
- radius=1;
-}
-#endif
diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp
index 0f4378acdd..697d91c863 100644
--- a/scene/3d/camera.cpp
+++ b/scene/3d/camera.cpp
@@ -94,6 +94,8 @@ bool Camera::_set(const StringName &p_name, const Variant &p_value) {
set_cull_mask(p_value);
} else if (p_name == "environment") {
set_environment(p_value);
+ } else if (p_name == "doppler/tracking") {
+ set_doppler_tracking(DopplerTracking(int(p_value)));
} else
return false;
@@ -131,6 +133,8 @@ bool Camera::_get(const StringName &p_name, Variant &r_ret) const {
r_ret = get_v_offset();
} else if (p_name == "environment") {
r_ret = get_environment();
+ } else if (p_name == "doppler/tracking") {
+ r_ret = get_doppler_tracking();
} else
return false;
@@ -171,6 +175,7 @@ void Camera::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"));
p_list->push_back(PropertyInfo(Variant::REAL, "h_offset"));
p_list->push_back(PropertyInfo(Variant::REAL, "v_offset"));
+ p_list->push_back(PropertyInfo(Variant::INT, "doppler/tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Fixed"));
}
void Camera::_update_camera() {
@@ -209,6 +214,9 @@ void Camera::_notification(int p_what) {
case NOTIFICATION_TRANSFORM_CHANGED: {
_request_camera_update();
+ if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {
+ velocity_tracker->update_position(get_global_transform().origin);
+ }
} break;
case NOTIFICATION_EXIT_WORLD: {
@@ -507,6 +515,22 @@ Camera::KeepAspect Camera::get_keep_aspect_mode() const {
return keep_aspect;
}
+void Camera::set_doppler_tracking(DopplerTracking p_tracking) {
+
+ if (doppler_tracking == p_tracking)
+ return;
+
+ doppler_tracking = p_tracking;
+ if (p_tracking != DOPPLER_TRACKING_DISABLED) {
+ velocity_tracker->set_track_fixed_step(doppler_tracking == DOPPLER_TRACKING_FIXED_STEP);
+ velocity_tracker->reset(get_global_transform().origin);
+ }
+}
+
+Camera::DopplerTracking Camera::get_doppler_tracking() const {
+ return doppler_tracking;
+}
+
void Camera::_bind_methods() {
ClassDB::bind_method(D_METHOD("project_ray_normal", "screen_point"), &Camera::project_ray_normal);
@@ -536,6 +560,8 @@ void Camera::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_environment:Environment"), &Camera::get_environment);
ClassDB::bind_method(D_METHOD("set_keep_aspect_mode", "mode"), &Camera::set_keep_aspect_mode);
ClassDB::bind_method(D_METHOD("get_keep_aspect_mode"), &Camera::get_keep_aspect_mode);
+ ClassDB::bind_method(D_METHOD("set_doppler_tracking", "mode"), &Camera::set_doppler_tracking);
+ ClassDB::bind_method(D_METHOD("get_doppler_tracking"), &Camera::get_doppler_tracking);
//ClassDB::bind_method(D_METHOD("_camera_make_current"),&Camera::_camera_make_current );
BIND_CONSTANT(PROJECTION_PERSPECTIVE);
@@ -543,6 +569,10 @@ void Camera::_bind_methods() {
BIND_CONSTANT(KEEP_WIDTH);
BIND_CONSTANT(KEEP_HEIGHT);
+
+ BIND_CONSTANT(DOPPLER_TRACKING_DISABLED)
+ BIND_CONSTANT(DOPPLER_TRACKING_IDLE_STEP)
+ BIND_CONSTANT(DOPPLER_TRACKING_FIXED_STEP)
}
float Camera::get_fov() const {
@@ -616,6 +646,14 @@ float Camera::get_h_offset() const {
return h_offset;
}
+Vector3 Camera::get_doppler_tracked_velocity() const {
+
+ if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {
+ return velocity_tracker->get_tracked_linear_velocity();
+ } else {
+ return Vector3();
+ }
+}
Camera::Camera() {
camera = VisualServer::get_singleton()->camera_create();
@@ -633,6 +671,8 @@ Camera::Camera() {
h_offset = 0;
VisualServer::get_singleton()->camera_set_cull_mask(camera, layers);
//active=false;
+ velocity_tracker.instance();
+ doppler_tracking = DOPPLER_TRACKING_DISABLED;
set_notify_transform(true);
}
diff --git a/scene/3d/camera.h b/scene/3d/camera.h
index 472cfaa008..43975892b4 100644
--- a/scene/3d/camera.h
+++ b/scene/3d/camera.h
@@ -31,6 +31,7 @@
#define CAMERA_H
#include "scene/3d/spatial.h"
+#include "scene/3d/spatial_velocity_tracker.h"
#include "scene/main/viewport.h"
#include "scene/resources/environment.h"
/**
@@ -52,6 +53,12 @@ public:
KEEP_HEIGHT
};
+ enum DopplerTracking {
+ DOPPLER_TRACKING_DISABLED,
+ DOPPLER_TRACKING_IDLE_STEP,
+ DOPPLER_TRACKING_FIXED_STEP
+ };
+
private:
bool force_change;
bool current;
@@ -80,6 +87,9 @@ private:
friend class Viewport;
void _update_audio_listener_state();
+ DopplerTracking doppler_tracking;
+ Ref<SpatialVelocityTracker> velocity_tracker;
+
protected:
void _update_camera();
virtual void _request_camera_update();
@@ -140,11 +150,17 @@ public:
void set_h_offset(float p_offset);
float get_h_offset() const;
+ void set_doppler_tracking(DopplerTracking p_tracking);
+ DopplerTracking get_doppler_tracking() const;
+
+ Vector3 get_doppler_tracked_velocity() const;
+
Camera();
~Camera();
};
VARIANT_ENUM_CAST(Camera::Projection);
VARIANT_ENUM_CAST(Camera::KeepAspect);
+VARIANT_ENUM_CAST(Camera::DopplerTracking);
#endif
diff --git a/scene/3d/collision_object.cpp b/scene/3d/collision_object.cpp
index 1b27313d3b..5a3d8e013f 100644
--- a/scene/3d/collision_object.cpp
+++ b/scene/3d/collision_object.cpp
@@ -30,17 +30,6 @@
#include "collision_object.h"
#include "scene/scene_string_names.h"
#include "servers/physics_server.h"
-void CollisionObject::_update_shapes_from_children() {
-
- shapes.clear();
- for (int i = 0; i < get_child_count(); i++) {
-
- Node *n = get_child(i);
- n->call("_add_to_collision_object", this);
- }
-
- _update_shapes();
-}
void CollisionObject::_notification(int p_what) {
@@ -87,91 +76,6 @@ void CollisionObject::_notification(int p_what) {
}
}
-void CollisionObject::_update_shapes() {
-
- if (!rid.is_valid())
- return;
-
- if (area)
- PhysicsServer::get_singleton()->area_clear_shapes(rid);
- else
- PhysicsServer::get_singleton()->body_clear_shapes(rid);
-
- for (int i = 0; i < shapes.size(); i++) {
-
- if (shapes[i].shape.is_null())
- continue;
- if (area)
- PhysicsServer::get_singleton()->area_add_shape(rid, shapes[i].shape->get_rid(), shapes[i].xform);
- else {
- PhysicsServer::get_singleton()->body_add_shape(rid, shapes[i].shape->get_rid(), shapes[i].xform);
- if (shapes[i].trigger)
- PhysicsServer::get_singleton()->body_set_shape_as_trigger(rid, i, shapes[i].trigger);
- }
- }
-}
-
-bool CollisionObject::_set(const StringName &p_name, const Variant &p_value) {
- String name = p_name;
-
- if (name == "shape_count") {
-
- shapes.resize(p_value);
- _update_shapes();
- _change_notify();
-
- } else if (name.begins_with("shapes/")) {
-
- int idx = name.get_slicec('/', 1).to_int();
- String what = name.get_slicec('/', 2);
- if (what == "shape")
- set_shape(idx, RefPtr(p_value));
- else if (what == "transform")
- set_shape_transform(idx, p_value);
- else if (what == "trigger")
- set_shape_as_trigger(idx, p_value);
-
- } else
- return false;
-
- return true;
-}
-
-bool CollisionObject::_get(const StringName &p_name, Variant &r_ret) const {
-
- String name = p_name;
-
- if (name == "shape_count") {
- r_ret = shapes.size();
- } else if (name.begins_with("shapes/")) {
-
- int idx = name.get_slicec('/', 1).to_int();
- String what = name.get_slicec('/', 2);
- if (what == "shape")
- r_ret = get_shape(idx);
- else if (what == "transform")
- r_ret = get_shape_transform(idx);
- else if (what == "trigger")
- r_ret = is_shape_set_as_trigger(idx);
-
- } else
- return false;
-
- return true;
-}
-
-void CollisionObject::_get_property_list(List<PropertyInfo> *p_list) const {
-
- p_list->push_back(PropertyInfo(Variant::INT, "shape_count", PROPERTY_HINT_RANGE, "0,256,1", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_NO_INSTANCE_STATE));
-
- for (int i = 0; i < shapes.size(); i++) {
- String path = "shapes/" + itos(i) + "/";
- p_list->push_back(PropertyInfo(Variant::OBJECT, path + "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_NO_INSTANCE_STATE));
- p_list->push_back(PropertyInfo(Variant::TRANSFORM, path + "transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_NO_INSTANCE_STATE));
- p_list->push_back(PropertyInfo(Variant::BOOL, path + "trigger", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_NO_INSTANCE_STATE));
- }
-}
-
void CollisionObject::_input_event(Node *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape) {
if (get_script_instance()) {
@@ -219,22 +123,27 @@ bool CollisionObject::is_ray_pickable() const {
void CollisionObject::_bind_methods() {
- ClassDB::bind_method(D_METHOD("add_shape", "shape:Shape", "transform"), &CollisionObject::add_shape, DEFVAL(Transform()));
- ClassDB::bind_method(D_METHOD("get_shape_count"), &CollisionObject::get_shape_count);
- ClassDB::bind_method(D_METHOD("set_shape", "shape_idx", "shape:Shape"), &CollisionObject::set_shape);
- ClassDB::bind_method(D_METHOD("set_shape_transform", "shape_idx", "transform"), &CollisionObject::set_shape_transform);
- // ClassDB::bind_method(D_METHOD("set_shape_transform","shape_idx","transform"),&CollisionObject::set_shape_transform);
- ClassDB::bind_method(D_METHOD("set_shape_as_trigger", "shape_idx", "enable"), &CollisionObject::set_shape_as_trigger);
- ClassDB::bind_method(D_METHOD("is_shape_set_as_trigger", "shape_idx"), &CollisionObject::is_shape_set_as_trigger);
- ClassDB::bind_method(D_METHOD("get_shape:Shape", "shape_idx"), &CollisionObject::get_shape);
- ClassDB::bind_method(D_METHOD("get_shape_transform", "shape_idx"), &CollisionObject::get_shape_transform);
- ClassDB::bind_method(D_METHOD("remove_shape", "shape_idx"), &CollisionObject::remove_shape);
- ClassDB::bind_method(D_METHOD("clear_shapes"), &CollisionObject::clear_shapes);
ClassDB::bind_method(D_METHOD("set_ray_pickable", "ray_pickable"), &CollisionObject::set_ray_pickable);
ClassDB::bind_method(D_METHOD("is_ray_pickable"), &CollisionObject::is_ray_pickable);
ClassDB::bind_method(D_METHOD("set_capture_input_on_drag", "enable"), &CollisionObject::set_capture_input_on_drag);
ClassDB::bind_method(D_METHOD("get_capture_input_on_drag"), &CollisionObject::get_capture_input_on_drag);
ClassDB::bind_method(D_METHOD("get_rid"), &CollisionObject::get_rid);
+ ClassDB::bind_method(D_METHOD("create_shape_owner", "owner:Object"), &CollisionObject::create_shape_owner);
+ ClassDB::bind_method(D_METHOD("remove_shape_owner", "owner_id"), &CollisionObject::remove_shape_owner);
+ ClassDB::bind_method(D_METHOD("get_shape_owners"), &CollisionObject::_get_shape_owners);
+ ClassDB::bind_method(D_METHOD("shape_owner_set_transform", "owner_id", "transform:Transform"), &CollisionObject::shape_owner_set_transform);
+ ClassDB::bind_method(D_METHOD("shape_owner_get_transform", "owner_id"), &CollisionObject::shape_owner_get_transform);
+ ClassDB::bind_method(D_METHOD("shape_owner_get_owner", "owner_id"), &CollisionObject::shape_owner_get_owner);
+ ClassDB::bind_method(D_METHOD("shape_owner_set_disabled", "owner_id", "disabled"), &CollisionObject::shape_owner_set_disabled);
+ ClassDB::bind_method(D_METHOD("is_shape_owner_disabled", "owner_id"), &CollisionObject::is_shape_owner_disabled);
+ ClassDB::bind_method(D_METHOD("shape_owner_add_shape", "owner_id", "shape:Shape"), &CollisionObject::shape_owner_add_shape);
+ ClassDB::bind_method(D_METHOD("shape_owner_get_shape_count", "owner_id"), &CollisionObject::shape_owner_get_shape_count);
+ ClassDB::bind_method(D_METHOD("shape_owner_get_shape", "owner_id", "shape_id"), &CollisionObject::shape_owner_get_shape);
+ ClassDB::bind_method(D_METHOD("shape_owner_get_shape_index", "owner_id", "shape_id"), &CollisionObject::shape_owner_get_shape_index);
+ ClassDB::bind_method(D_METHOD("shape_owner_remove_shape", "owner_id", "shape_id"), &CollisionObject::shape_owner_remove_shape);
+ ClassDB::bind_method(D_METHOD("shape_owner_clear_shapes", "owner_id"), &CollisionObject::shape_owner_clear_shapes);
+ ClassDB::bind_method(D_METHOD("shape_find_owner", "shape_index"), &CollisionObject::shape_find_owner);
+
BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_pos"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx")));
ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_pos"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx")));
@@ -245,72 +154,186 @@ void CollisionObject::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "input_capture_on_drag"), "set_capture_input_on_drag", "get_capture_input_on_drag");
}
-void CollisionObject::add_shape(const Ref<Shape> &p_shape, const Transform &p_transform) {
+uint32_t CollisionObject::create_shape_owner(Object *p_owner) {
+
+ ShapeData sd;
+ uint32_t id;
+
+ if (shapes.size() == 0) {
+ id = 1;
+ } else {
+ id = shapes.back()->key() + 1;
+ }
+
+ sd.owner = p_owner;
- ShapeData sdata;
- sdata.shape = p_shape;
- sdata.xform = p_transform;
- shapes.push_back(sdata);
- _update_shapes();
+ shapes[id] = sd;
+
+ return id;
}
-int CollisionObject::get_shape_count() const {
- return shapes.size();
+void CollisionObject::remove_shape_owner(uint32_t owner) {
+
+ ERR_FAIL_COND(!shapes.has(owner));
+
+ shape_owner_clear_shapes(owner);
+
+ shapes.erase(owner);
}
-void CollisionObject::set_shape(int p_shape_idx, const Ref<Shape> &p_shape) {
- ERR_FAIL_INDEX(p_shape_idx, shapes.size());
- shapes[p_shape_idx].shape = p_shape;
- _update_shapes();
+void CollisionObject::shape_owner_set_disabled(uint32_t p_owner, bool p_disabled) {
+ ERR_FAIL_COND(!shapes.has(p_owner));
+
+ ShapeData &sd = shapes[p_owner];
+ sd.disabled = p_disabled;
+ for (int i = 0; i < sd.shapes.size(); i++) {
+ if (area) {
+ PhysicsServer::get_singleton()->area_set_shape_disabled(rid, sd.shapes[i].index, p_disabled);
+ } else {
+ PhysicsServer::get_singleton()->body_set_shape_disabled(rid, sd.shapes[i].index, p_disabled);
+ }
+ }
+}
+
+bool CollisionObject::is_shape_owner_disabled(uint32_t p_owner) const {
+
+ ERR_FAIL_COND_V(!shapes.has(p_owner), false);
+
+ return shapes[p_owner].disabled;
+}
+
+void CollisionObject::get_shape_owners(List<uint32_t> *r_owners) {
+
+ for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) {
+ r_owners->push_back(E->key());
+ }
+}
+
+Array CollisionObject::_get_shape_owners() {
+
+ Array ret;
+ for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) {
+ ret.push_back(E->key());
+ }
+
+ return ret;
+}
+
+void CollisionObject::shape_owner_set_transform(uint32_t p_owner, const Transform &p_transform) {
+
+ ERR_FAIL_COND(!shapes.has(p_owner));
+
+ ShapeData &sd = shapes[p_owner];
+ sd.xform = p_transform;
+ for (int i = 0; i < sd.shapes.size(); i++) {
+ if (area) {
+ PhysicsServer::get_singleton()->area_set_shape_transform(rid, sd.shapes[i].index, p_transform);
+ } else {
+ PhysicsServer::get_singleton()->body_set_shape_transform(rid, sd.shapes[i].index, p_transform);
+ }
+ }
+}
+Transform CollisionObject::shape_owner_get_transform(uint32_t p_owner) const {
+
+ ERR_FAIL_COND_V(!shapes.has(p_owner), Transform());
+
+ return shapes[p_owner].xform;
}
-void CollisionObject::set_shape_transform(int p_shape_idx, const Transform &p_transform) {
+Object *CollisionObject::shape_owner_get_owner(uint32_t p_owner) const {
- ERR_FAIL_INDEX(p_shape_idx, shapes.size());
- shapes[p_shape_idx].xform = p_transform;
+ ERR_FAIL_COND_V(!shapes.has(p_owner), NULL);
- _update_shapes();
+ return shapes[p_owner].owner;
}
-Ref<Shape> CollisionObject::get_shape(int p_shape_idx) const {
+void CollisionObject::shape_owner_add_shape(uint32_t p_owner, const Ref<Shape> &p_shape) {
+
+ ERR_FAIL_COND(!shapes.has(p_owner));
+ ERR_FAIL_COND(p_shape.is_null());
+
+ ShapeData &sd = shapes[p_owner];
+ ShapeData::ShapeBase s;
+ s.index = total_subshapes;
+ s.shape = p_shape;
+ if (area) {
+ PhysicsServer::get_singleton()->area_add_shape(rid, p_shape->get_rid(), sd.xform);
+ } else {
+ PhysicsServer::get_singleton()->body_add_shape(rid, p_shape->get_rid(), sd.xform);
+ }
+ sd.shapes.push_back(s);
- ERR_FAIL_INDEX_V(p_shape_idx, shapes.size(), Ref<Shape>());
- return shapes[p_shape_idx].shape;
+ total_subshapes++;
}
-Transform CollisionObject::get_shape_transform(int p_shape_idx) const {
+int CollisionObject::shape_owner_get_shape_count(uint32_t p_owner) const {
- ERR_FAIL_INDEX_V(p_shape_idx, shapes.size(), Transform());
- return shapes[p_shape_idx].xform;
+ ERR_FAIL_COND_V(!shapes.has(p_owner), 0);
+
+ return shapes[p_owner].shapes.size();
}
-void CollisionObject::remove_shape(int p_shape_idx) {
+Ref<Shape> CollisionObject::shape_owner_get_shape(uint32_t p_owner, int p_shape) const {
- ERR_FAIL_INDEX(p_shape_idx, shapes.size());
- shapes.remove(p_shape_idx);
+ ERR_FAIL_COND_V(!shapes.has(p_owner), Ref<Shape>());
+ ERR_FAIL_INDEX_V(p_shape, shapes[p_owner].shapes.size(), Ref<Shape>());
- _update_shapes();
+ return shapes[p_owner].shapes[p_shape].shape;
}
+int CollisionObject::shape_owner_get_shape_index(uint32_t p_owner, int p_shape) const {
+
+ ERR_FAIL_COND_V(!shapes.has(p_owner), -1);
+ ERR_FAIL_INDEX_V(p_shape, shapes[p_owner].shapes.size(), -1);
+
+ return shapes[p_owner].shapes[p_shape].index;
+}
+
+void CollisionObject::shape_owner_remove_shape(uint32_t p_owner, int p_shape) {
-void CollisionObject::clear_shapes() {
+ ERR_FAIL_COND(!shapes.has(p_owner));
+ ERR_FAIL_INDEX(p_shape, shapes[p_owner].shapes.size());
- shapes.clear();
+ int index_to_remove = shapes[p_owner].shapes[p_shape].index;
+ if (area) {
+ PhysicsServer::get_singleton()->area_remove_shape(rid, index_to_remove);
+ } else {
+ PhysicsServer::get_singleton()->body_remove_shape(rid, index_to_remove);
+ }
+
+ shapes[p_owner].shapes.remove(p_shape);
+
+ for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) {
+ for (int i = 0; i < E->get().shapes.size(); i++) {
+ if (E->get().shapes[i].index > index_to_remove) {
+ E->get().shapes[i].index -= 1;
+ }
+ }
+ }
- _update_shapes();
+ total_subshapes--;
}
-void CollisionObject::set_shape_as_trigger(int p_shape_idx, bool p_trigger) {
+void CollisionObject::shape_owner_clear_shapes(uint32_t p_owner) {
- ERR_FAIL_INDEX(p_shape_idx, shapes.size());
- shapes[p_shape_idx].trigger = p_trigger;
- if (!area && rid.is_valid()) {
+ ERR_FAIL_COND(!shapes.has(p_owner));
- PhysicsServer::get_singleton()->body_set_shape_as_trigger(rid, p_shape_idx, p_trigger);
+ while (shape_owner_get_shape_count(p_owner) > 0) {
+ shape_owner_remove_shape(p_owner, 0);
}
}
-bool CollisionObject::is_shape_set_as_trigger(int p_shape_idx) const {
+uint32_t CollisionObject::shape_find_owner(int p_shape_index) const {
- ERR_FAIL_INDEX_V(p_shape_idx, shapes.size(), false);
- return shapes[p_shape_idx].trigger;
+ ERR_FAIL_INDEX_V(p_shape_index, total_subshapes, 0);
+
+ for (const Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) {
+ for (int i = 0; i < E->get().shapes.size(); i++) {
+ if (E->get().shapes[i].index == p_shape_index) {
+ return E->key();
+ }
+ }
+ }
+
+ //in theory it should be unreachable
+ return 0;
}
CollisionObject::CollisionObject(RID p_rid, bool p_area) {
@@ -320,6 +343,8 @@ CollisionObject::CollisionObject(RID p_rid, bool p_area) {
capture_input_on_drag = false;
ray_pickable = true;
set_notify_transform(true);
+ total_subshapes = 0;
+
if (p_area) {
PhysicsServer::get_singleton()->area_attach_object_instance_ID(rid, get_instance_ID());
} else {
diff --git a/scene/3d/collision_object.h b/scene/3d/collision_object.h
index 3822fb0d5a..6c13e5d505 100644
--- a/scene/3d/collision_object.h
+++ b/scene/3d/collision_object.h
@@ -41,33 +41,36 @@ class CollisionObject : public Spatial {
RID rid;
struct ShapeData {
+
+ Object *owner;
Transform xform;
- Ref<Shape> shape;
- bool trigger;
+ struct ShapeBase {
+ Ref<Shape> shape;
+ int index;
+ };
+
+ Vector<ShapeBase> shapes;
+ bool disabled;
ShapeData() {
- trigger = false;
+ disabled = false;
+ owner = NULL;
}
};
+ int total_subshapes;
+
+ Map<uint32_t, ShapeData> shapes;
+
bool capture_input_on_drag;
bool ray_pickable;
- Vector<ShapeData> shapes;
void _update_pickable();
- void _update_shapes();
-
- friend class CollisionShape;
- friend class CollisionPolygon;
- void _update_shapes_from_children();
protected:
CollisionObject(RID p_rid, bool p_area);
void _notification(int p_what);
- 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();
friend class Viewport;
virtual void _input_event(Node *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape);
@@ -75,16 +78,27 @@ protected:
virtual void _mouse_exit();
public:
- void add_shape(const Ref<Shape> &p_shape, const Transform &p_transform = Transform());
- int get_shape_count() const;
- void set_shape(int p_shape_idx, const Ref<Shape> &p_shape);
- void set_shape_transform(int p_shape_idx, const Transform &p_transform);
- Ref<Shape> get_shape(int p_shape_idx) const;
- Transform get_shape_transform(int p_shape_idx) const;
- void remove_shape(int p_shape_idx);
- void clear_shapes();
- void set_shape_as_trigger(int p_shape_idx, bool p_trigger);
- bool is_shape_set_as_trigger(int p_shape_idx) const;
+ uint32_t create_shape_owner(Object *p_owner);
+ void remove_shape_owner(uint32_t owner);
+ void get_shape_owners(List<uint32_t> *r_owners);
+ Array _get_shape_owners();
+
+ void shape_owner_set_transform(uint32_t p_owner, const Transform &p_transform);
+ Transform shape_owner_get_transform(uint32_t p_owner) const;
+ Object *shape_owner_get_owner(uint32_t p_owner) const;
+
+ void shape_owner_set_disabled(uint32_t p_owner, bool p_disabled);
+ bool is_shape_owner_disabled(uint32_t p_owner) const;
+
+ void shape_owner_add_shape(uint32_t p_owner, const Ref<Shape> &p_shape);
+ int shape_owner_get_shape_count(uint32_t p_owner) const;
+ Ref<Shape> shape_owner_get_shape(uint32_t p_owner, int p_shape) const;
+ int shape_owner_get_shape_index(uint32_t p_owner, int p_shape) const;
+
+ void shape_owner_remove_shape(uint32_t p_owner, int p_shape);
+ void shape_owner_clear_shapes(uint32_t p_owner);
+
+ uint32_t shape_find_owner(int p_shape_index) const;
void set_ray_pickable(bool p_ray_pickable);
bool is_ray_pickable() const;
diff --git a/scene/3d/collision_polygon.cpp b/scene/3d/collision_polygon.cpp
index d9321f7134..0c61c96d07 100644
--- a/scene/3d/collision_polygon.cpp
+++ b/scene/3d/collision_polygon.cpp
@@ -33,186 +33,82 @@
#include "scene/resources/concave_polygon_shape.h"
#include "scene/resources/convex_polygon_shape.h"
-void CollisionPolygon::_add_to_collision_object(Object *p_obj) {
+void CollisionPolygon::_build_polygon() {
- if (!can_update_body)
+ if (!parent)
return;
- CollisionObject *co = p_obj->cast_to<CollisionObject>();
- ERR_FAIL_COND(!co);
+ parent->shape_owner_clear_shapes(owner_id);
if (polygon.size() == 0)
return;
- bool solids = build_mode == BUILD_SOLIDS;
-
Vector<Vector<Vector2> > decomp = Geometry::decompose_polygon(polygon);
if (decomp.size() == 0)
return;
- if (true || solids) {
-
- //here comes the sun, lalalala
- //decompose concave into multiple convex polygons and add them
- shape_from = co->get_shape_count();
- for (int i = 0; i < decomp.size(); i++) {
- Ref<ConvexPolygonShape> convex = memnew(ConvexPolygonShape);
- PoolVector<Vector3> cp;
- int cs = decomp[i].size();
- cp.resize(cs * 2);
- {
- PoolVector<Vector3>::Write w = cp.write();
- int idx = 0;
- for (int j = 0; j < cs; j++) {
-
- Vector2 d = decomp[i][j];
- w[idx++] = Vector3(d.x, d.y, depth * 0.5);
- w[idx++] = Vector3(d.x, d.y, -depth * 0.5);
- }
+ //here comes the sun, lalalala
+ //decompose concave into multiple convex polygons and add them
+
+ for (int i = 0; i < decomp.size(); i++) {
+ Ref<ConvexPolygonShape> convex = memnew(ConvexPolygonShape);
+ PoolVector<Vector3> cp;
+ int cs = decomp[i].size();
+ cp.resize(cs * 2);
+ {
+ PoolVector<Vector3>::Write w = cp.write();
+ int idx = 0;
+ for (int j = 0; j < cs; j++) {
+
+ Vector2 d = decomp[i][j];
+ w[idx++] = Vector3(d.x, d.y, depth * 0.5);
+ w[idx++] = Vector3(d.x, d.y, -depth * 0.5);
}
-
- convex->set_points(cp);
- co->add_shape(convex, get_transform());
- }
- shape_to = co->get_shape_count() - 1;
- if (shape_to < shape_from) {
- shape_from = -1;
- shape_to = -1;
- }
-
- } else {
-#if 0
- Ref<ConcavePolygonShape> concave = memnew( ConcavePolygonShape );
-
- PoolVector<Vector2> segments;
- segments.resize(polygon.size()*2);
- PoolVector<Vector2>::Write w=segments.write();
-
- for(int i=0;i<polygon.size();i++) {
- w[(i<<1)+0]=polygon[i];
- w[(i<<1)+1]=polygon[(i+1)%polygon.size()];
}
- w=PoolVector<Vector2>::Write();
- concave->set_segments(segments);
-
- co->add_shape(concave,get_transform());
-#endif
+ convex->set_points(cp);
+ parent->shape_owner_add_shape(owner_id, convex);
+ parent->shape_owner_set_disabled(owner_id, disabled);
}
-
- //co->add_shape(shape,get_transform());
-}
-
-void CollisionPolygon::_update_parent() {
-
- if (!can_update_body)
- return;
-
- Node *parent = get_parent();
- if (!parent)
- return;
- CollisionObject *co = parent->cast_to<CollisionObject>();
- if (!co)
- return;
- co->_update_shapes_from_children();
-}
-
-void CollisionPolygon::_set_shape_range(const Vector2 &p_range) {
-
- shape_from = p_range.x;
- shape_to = p_range.y;
-}
-
-Vector2 CollisionPolygon::_get_shape_range() const {
-
- return Vector2(shape_from, shape_to);
}
void CollisionPolygon::_notification(int p_what) {
switch (p_what) {
- case NOTIFICATION_ENTER_TREE: {
- can_update_body = get_tree()->is_editor_hint();
- set_notify_local_transform(!can_update_body);
- //indicator_instance = VisualServer::get_singleton()->instance_create2(indicator,get_world()->get_scenario());
- } break;
- case NOTIFICATION_EXIT_TREE: {
- can_update_body = false;
- set_notify_local_transform(false);
- } break;
- case NOTIFICATION_TRANSFORM_CHANGED: {
-
- if (!is_inside_tree())
- break;
- if (can_update_body) {
- _update_parent();
+ case NOTIFICATION_PARENTED: {
+ parent = get_parent()->cast_to<CollisionObject>();
+ if (parent) {
+ owner_id = parent->create_shape_owner(this);
+ _build_polygon();
+ parent->shape_owner_set_transform(owner_id, get_transform());
+ parent->shape_owner_set_disabled(owner_id, disabled);
}
-
} break;
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
- if (!can_update_body && shape_from >= 0 && shape_to >= 0) {
-
- CollisionObject *co = get_parent()->cast_to<CollisionObject>();
- if (co) {
- for (int i = shape_from; i <= shape_to; i++) {
- co->set_shape_transform(i, get_transform());
- }
- }
- }
- } break;
-#if 0
- case NOTIFICATION_DRAW: {
- for(int i=0;i<polygon.size();i++) {
-
- Vector2 p = polygon[i];
- Vector2 n = polygon[(i+1)%polygon.size()];
- draw_line(p,n,Color(0,0.6,0.7,0.5),3);
+ if (parent) {
+ parent->shape_owner_set_transform(owner_id, get_transform());
}
- Vector< Vector<Vector2> > decomp = Geometry::decompose_polygon(polygon);
-#define DEBUG_DECOMPOSE
-#ifdef DEBUG_DECOMPOSE
- Color c(0.4,0.9,0.1);
- for(int i=0;i<decomp.size();i++) {
-
- c.set_hsv( Math::fmod(c.get_h() + 0.738,1),c.get_s(),c.get_v(),0.5);
- draw_colored_polygon(decomp[i],c);
+ } break;
+ case NOTIFICATION_UNPARENTED: {
+ if (parent) {
+ parent->remove_shape_owner(owner_id);
}
-#endif
-
+ owner_id = 0;
+ parent = NULL;
} break;
-#endif
}
}
void CollisionPolygon::set_polygon(const Vector<Point2> &p_polygon) {
polygon = p_polygon;
- if (can_update_body) {
-
- for (int i = 0; i < polygon.size(); i++) {
-
- Vector3 p1(polygon[i].x, polygon[i].y, depth * 0.5);
-
- if (i == 0)
- aabb = Rect3(p1, Vector3());
- else
- aabb.expand_to(p1);
-
- Vector3 p2(polygon[i].x, polygon[i].y, -depth * 0.5);
- aabb.expand_to(p2);
- }
- if (aabb == Rect3()) {
-
- aabb = Rect3(Vector3(-1, -1, -1), Vector3(2, 2, 2));
- } else {
- aabb.position -= aabb.size * 0.3;
- aabb.size += aabb.size * 0.6;
- }
- _update_parent();
+ if (parent) {
+ _build_polygon();
}
+ update_configuration_warning();
update_gizmo();
}
@@ -221,20 +117,6 @@ Vector<Point2> CollisionPolygon::get_polygon() const {
return polygon;
}
-void CollisionPolygon::set_build_mode(BuildMode p_mode) {
-
- ERR_FAIL_INDEX(p_mode, 2);
- build_mode = p_mode;
- if (!can_update_body)
- return;
- _update_parent();
-}
-
-CollisionPolygon::BuildMode CollisionPolygon::get_build_mode() const {
-
- return build_mode;
-}
-
Rect3 CollisionPolygon::get_item_rect() const {
return aabb;
@@ -243,9 +125,7 @@ Rect3 CollisionPolygon::get_item_rect() const {
void CollisionPolygon::set_depth(float p_depth) {
depth = p_depth;
- if (!can_update_body)
- return;
- _update_parent();
+ _build_polygon();
update_gizmo();
}
@@ -254,6 +134,17 @@ float CollisionPolygon::get_depth() const {
return depth;
}
+void CollisionPolygon::set_disabled(bool p_disabled) {
+ disabled = p_disabled;
+ if (parent) {
+ parent->shape_owner_set_disabled(owner_id, p_disabled);
+ }
+}
+
+bool CollisionPolygon::is_disabled() const {
+ return disabled;
+}
+
String CollisionPolygon::get_configuration_warning() const {
if (!get_parent()->cast_to<CollisionObject>()) {
@@ -269,36 +160,26 @@ String CollisionPolygon::get_configuration_warning() const {
void CollisionPolygon::_bind_methods() {
- ClassDB::bind_method(D_METHOD("_add_to_collision_object"), &CollisionPolygon::_add_to_collision_object);
-
- ClassDB::bind_method(D_METHOD("set_build_mode", "build_mode"), &CollisionPolygon::set_build_mode);
- ClassDB::bind_method(D_METHOD("get_build_mode"), &CollisionPolygon::get_build_mode);
-
ClassDB::bind_method(D_METHOD("set_depth", "depth"), &CollisionPolygon::set_depth);
ClassDB::bind_method(D_METHOD("get_depth"), &CollisionPolygon::get_depth);
ClassDB::bind_method(D_METHOD("set_polygon", "polygon"), &CollisionPolygon::set_polygon);
ClassDB::bind_method(D_METHOD("get_polygon"), &CollisionPolygon::get_polygon);
- ClassDB::bind_method(D_METHOD("_set_shape_range", "shape_range"), &CollisionPolygon::_set_shape_range);
- ClassDB::bind_method(D_METHOD("_get_shape_range"), &CollisionPolygon::_get_shape_range);
-
- ClassDB::bind_method(D_METHOD("get_collision_object_first_shape"), &CollisionPolygon::get_collision_object_first_shape);
- ClassDB::bind_method(D_METHOD("get_collision_object_last_shape"), &CollisionPolygon::get_collision_object_last_shape);
+ ClassDB::bind_method(D_METHOD("set_disabled", "disabled"), &CollisionPolygon::set_disabled);
+ ClassDB::bind_method(D_METHOD("is_disabled"), &CollisionPolygon::is_disabled);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "build_mode", PROPERTY_HINT_ENUM, "Solids,Triangles"), "set_build_mode", "get_build_mode");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "depth"), "set_depth", "get_depth");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "shape_range", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_shape_range", "_get_shape_range");
}
CollisionPolygon::CollisionPolygon() {
- shape_from = -1;
- shape_to = -1;
- can_update_body = false;
-
aabb = Rect3(Vector3(-1, -1, -1), Vector3(2, 2, 2));
- build_mode = BUILD_SOLIDS;
depth = 1.0;
+ set_notify_local_transform(true);
+ parent = NULL;
+ owner_id = 0;
+ disabled = false;
}
diff --git a/scene/3d/collision_polygon.h b/scene/3d/collision_polygon.h
index d45b4738ae..beefae182c 100644
--- a/scene/3d/collision_polygon.h
+++ b/scene/3d/collision_polygon.h
@@ -33,55 +33,42 @@
#include "scene/3d/spatial.h"
#include "scene/resources/shape.h"
+class CollisionObject;
class CollisionPolygon : public Spatial {
GDCLASS(CollisionPolygon, Spatial);
-public:
- enum BuildMode {
- BUILD_SOLIDS,
- BUILD_TRIANGLES,
- };
-
protected:
float depth;
Rect3 aabb;
- BuildMode build_mode;
Vector<Point2> polygon;
- void _add_to_collision_object(Object *p_obj);
- void _update_parent();
+ uint32_t owner_id;
+ CollisionObject *parent;
- bool can_update_body;
- int shape_from;
- int shape_to;
+ bool disabled;
- void _set_shape_range(const Vector2 &p_range);
- Vector2 _get_shape_range() const;
+ void _build_polygon();
protected:
void _notification(int p_what);
static void _bind_methods();
public:
- void set_build_mode(BuildMode p_mode);
- BuildMode get_build_mode() const;
-
void set_depth(float p_depth);
float get_depth() const;
void set_polygon(const Vector<Point2> &p_polygon);
Vector<Point2> get_polygon() const;
- virtual Rect3 get_item_rect() const;
+ void set_disabled(bool p_disabled);
+ bool is_disabled() const;
- int get_collision_object_first_shape() const { return shape_from; }
- int get_collision_object_last_shape() const { return shape_to; }
+ virtual Rect3 get_item_rect() const;
String get_configuration_warning() const;
CollisionPolygon();
};
-VARIANT_ENUM_CAST(CollisionPolygon::BuildMode);
#endif // COLLISION_POLYGON_H
diff --git a/scene/3d/collision_shape.cpp b/scene/3d/collision_shape.cpp
new file mode 100644
index 0000000000..a7cfc6fef2
--- /dev/null
+++ b/scene/3d/collision_shape.cpp
@@ -0,0 +1,214 @@
+/*************************************************************************/
+/* body_shape.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (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 "collision_shape.h"
+#include "scene/resources/box_shape.h"
+#include "scene/resources/capsule_shape.h"
+#include "scene/resources/concave_polygon_shape.h"
+#include "scene/resources/convex_polygon_shape.h"
+#include "scene/resources/plane_shape.h"
+#include "scene/resources/ray_shape.h"
+#include "scene/resources/sphere_shape.h"
+#include "servers/visual_server.h"
+//TODO: Implement CylinderShape and HeightMapShape?
+#include "mesh_instance.h"
+#include "physics_body.h"
+#include "quick_hull.h"
+
+void CollisionShape::make_convex_from_brothers() {
+
+ Node *p = get_parent();
+ if (!p)
+ return;
+
+ for (int i = 0; i < p->get_child_count(); i++) {
+
+ Node *n = p->get_child(i);
+ if (n->cast_to<MeshInstance>()) {
+
+ MeshInstance *mi = n->cast_to<MeshInstance>();
+ Ref<Mesh> m = mi->get_mesh();
+ if (m.is_valid()) {
+
+ Ref<Shape> s = m->create_convex_shape();
+ set_shape(s);
+ }
+ }
+ }
+}
+
+void CollisionShape::_notification(int p_what) {
+
+ switch (p_what) {
+
+ case NOTIFICATION_PARENTED: {
+ parent = get_parent()->cast_to<CollisionObject>();
+ if (parent) {
+ owner_id = parent->create_shape_owner(this);
+ if (shape.is_valid()) {
+ parent->shape_owner_add_shape(owner_id, shape);
+ }
+ parent->shape_owner_set_transform(owner_id, get_transform());
+ parent->shape_owner_set_disabled(owner_id, disabled);
+ }
+ } break;
+ case NOTIFICATION_ENTER_TREE: {
+ if (get_tree()->is_debugging_collisions_hint()) {
+ _create_debug_shape();
+ }
+
+ } break;
+ case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
+ if (parent) {
+ parent->shape_owner_set_transform(owner_id, get_transform());
+ }
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+ if (parent) {
+ parent->remove_shape_owner(owner_id);
+ }
+ owner_id = 0;
+ parent = NULL;
+ } break;
+ case NOTIFICATION_UNPARENTED: {
+ if (parent) {
+ parent->remove_shape_owner(owner_id);
+ }
+ owner_id = 0;
+ parent = NULL;
+ } break;
+ }
+}
+
+void CollisionShape::resource_changed(RES res) {
+
+ update_gizmo();
+}
+
+String CollisionShape::get_configuration_warning() const {
+
+ if (!get_parent()->cast_to<CollisionObject>()) {
+ return TTR("CollisionShape only serves to provide a collision shape to a CollisionObject derived node. Please only use it as a child of Area, StaticBody, RigidBody, KinematicBody, etc. to give them a shape.");
+ }
+
+ if (!shape.is_valid()) {
+ return TTR("A shape must be provided for CollisionShape to function. Please create a shape resource for it!");
+ }
+
+ return String();
+}
+
+void CollisionShape::_bind_methods() {
+
+ //not sure if this should do anything
+ ClassDB::bind_method(D_METHOD("resource_changed", "resource:Resource"), &CollisionShape::resource_changed);
+ ClassDB::bind_method(D_METHOD("set_shape", "shape:Shape"), &CollisionShape::set_shape);
+ ClassDB::bind_method(D_METHOD("get_shape:Shape"), &CollisionShape::get_shape);
+ ClassDB::bind_method(D_METHOD("set_disabled", "enable"), &CollisionShape::set_disabled);
+ ClassDB::bind_method(D_METHOD("is_disabled"), &CollisionShape::is_disabled);
+ ClassDB::bind_method(D_METHOD("make_convex_from_brothers"), &CollisionShape::make_convex_from_brothers);
+ ClassDB::set_method_flags("CollisionShape", "make_convex_from_brothers", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
+
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape"), "set_shape", "get_shape");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
+}
+
+void CollisionShape::set_shape(const Ref<Shape> &p_shape) {
+
+ if (!shape.is_null())
+ shape->unregister_owner(this);
+ shape = p_shape;
+ if (!shape.is_null())
+ shape->register_owner(this);
+ update_gizmo();
+ if (parent) {
+ parent->shape_owner_clear_shapes(owner_id);
+ if (shape.is_valid()) {
+ parent->shape_owner_add_shape(owner_id, shape);
+ }
+ }
+
+ update_configuration_warning();
+}
+
+Ref<Shape> CollisionShape::get_shape() const {
+
+ return shape;
+}
+
+void CollisionShape::set_disabled(bool p_disabled) {
+
+ disabled = p_disabled;
+ update_gizmo();
+ if (parent) {
+ parent->shape_owner_set_disabled(owner_id, p_disabled);
+ }
+}
+
+bool CollisionShape::is_disabled() const {
+
+ return disabled;
+}
+
+CollisionShape::CollisionShape() {
+
+ //indicator = VisualServer::get_singleton()->mesh_create();
+ disabled = false;
+ debug_shape = NULL;
+ parent = NULL;
+ owner_id = 0;
+ set_notify_local_transform(true);
+}
+
+CollisionShape::~CollisionShape() {
+ if (!shape.is_null())
+ shape->unregister_owner(this);
+ //VisualServer::get_singleton()->free(indicator);
+}
+
+void CollisionShape::_create_debug_shape() {
+
+ if (debug_shape) {
+ debug_shape->queue_delete();
+ debug_shape = NULL;
+ }
+
+ Ref<Shape> s = get_shape();
+
+ if (s.is_null())
+ return;
+
+ Ref<Mesh> mesh = s->get_debug_mesh();
+
+ MeshInstance *mi = memnew(MeshInstance);
+ mi->set_mesh(mesh);
+
+ add_child(mi);
+ debug_shape = mi;
+}
diff --git a/scene/3d/body_shape.h b/scene/3d/collision_shape.h
index f4392dda62..277e0dfa77 100644
--- a/scene/3d/body_shape.h
+++ b/scene/3d/collision_shape.h
@@ -32,7 +32,7 @@
#include "scene/3d/spatial.h"
#include "scene/resources/shape.h"
-
+class CollisionObject;
class CollisionShape : public Spatial {
GDCLASS(CollisionShape, Spatial);
@@ -40,34 +40,13 @@ class CollisionShape : public Spatial {
Ref<Shape> shape;
- /*
- RID _get_visual_instance_rid() const;
-
-
- void _update_indicator();
-
- RID material;
- RID indicator;
- RID indicator_instance;
- */
+ uint32_t owner_id;
+ CollisionObject *parent;
Node *debug_shape;
void resource_changed(RES res);
-
- bool updating_body;
- bool unparenting;
- bool trigger;
-
- bool can_update_body;
-
- int update_shape_index;
-
- void _update_body();
- void _add_to_collision_object(Object *p_cshape);
-
- void _set_update_shape_index(int p_index);
- int _get_update_shape_index() const;
+ bool disabled;
void _create_debug_shape();
@@ -81,13 +60,8 @@ public:
void set_shape(const Ref<Shape> &p_shape);
Ref<Shape> get_shape() const;
- void set_updating_body(bool p_update);
- bool is_updating_body() const;
-
- void set_trigger(bool p_trigger);
- bool is_trigger() const;
-
- int get_collision_object_shape_index() const { return _get_update_shape_index(); }
+ void set_disabled(bool p_disabled);
+ bool is_disabled() const;
String get_configuration_warning() const;
diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp
index adca1492c3..7aaf4a6e3d 100644
--- a/scene/3d/gi_probe.cpp
+++ b/scene/3d/gi_probe.cpp
@@ -95,6 +95,16 @@ float GIProbeData::get_bias() const {
return VS::get_singleton()->gi_probe_get_bias(probe);
}
+void GIProbeData::set_normal_bias(float p_range) {
+
+ VS::get_singleton()->gi_probe_set_normal_bias(probe, p_range);
+}
+
+float GIProbeData::get_normal_bias() const {
+
+ return VS::get_singleton()->gi_probe_get_normal_bias(probe);
+}
+
void GIProbeData::set_propagation(float p_range) {
VS::get_singleton()->gi_probe_set_propagation(probe, p_range);
@@ -158,6 +168,9 @@ void GIProbeData::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bias", "bias"), &GIProbeData::set_bias);
ClassDB::bind_method(D_METHOD("get_bias"), &GIProbeData::get_bias);
+ ClassDB::bind_method(D_METHOD("set_normal_bias", "bias"), &GIProbeData::set_normal_bias);
+ ClassDB::bind_method(D_METHOD("get_normal_bias"), &GIProbeData::get_normal_bias);
+
ClassDB::bind_method(D_METHOD("set_propagation", "propagation"), &GIProbeData::set_propagation);
ClassDB::bind_method(D_METHOD("get_propagation"), &GIProbeData::get_propagation);
@@ -175,6 +188,7 @@ void GIProbeData::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "dynamic_range", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_dynamic_range", "get_dynamic_range");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "energy", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_energy", "get_energy");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "bias", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_bias", "get_bias");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "normal_bias", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_normal_bias", "get_normal_bias");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "propagation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_propagation", "get_propagation");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_interior", "is_interior");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "compress", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_compress", "is_compressed");
@@ -265,6 +279,18 @@ float GIProbe::get_bias() const {
return bias;
}
+void GIProbe::set_normal_bias(float p_normal_bias) {
+
+ normal_bias = p_normal_bias;
+ if (probe_data.is_valid()) {
+ probe_data->set_normal_bias(normal_bias);
+ }
+}
+float GIProbe::get_normal_bias() const {
+
+ return normal_bias;
+}
+
void GIProbe::set_propagation(float p_propagation) {
propagation = p_propagation;
@@ -973,7 +999,7 @@ GIProbe::Baker::MaterialCache GIProbe::_get_material_cache(Ref<Material> p_mater
return mc;
}
-void GIProbe::_plot_mesh(const Transform &p_xform, Ref<ArrayMesh> &p_mesh, Baker *p_baker, const Vector<Ref<Material> > &p_materials, const Ref<Material> &p_override_material) {
+void GIProbe::_plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, Baker *p_baker, const Vector<Ref<Material> > &p_materials, const Ref<Material> &p_override_material) {
for (int i = 0; i < p_mesh->get_surface_count(); i++) {
@@ -1067,7 +1093,7 @@ void GIProbe::_find_meshes(Node *p_at_node, Baker *p_baker) {
MeshInstance *mi = p_at_node->cast_to<MeshInstance>();
if (mi && mi->get_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT)) {
- Ref<ArrayMesh> mesh = mi->get_mesh();
+ Ref<Mesh> mesh = mi->get_mesh();
if (mesh.is_valid()) {
Rect3 aabb = mesh->get_aabb();
@@ -1094,7 +1120,7 @@ void GIProbe::_find_meshes(Node *p_at_node, Baker *p_baker) {
for (int i = 0; i < meshes.size(); i += 2) {
Transform mxf = meshes[i];
- Ref<ArrayMesh> mesh = meshes[i + 1];
+ Ref<Mesh> mesh = meshes[i + 1];
if (!mesh.is_valid())
continue;
@@ -1261,6 +1287,7 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
probe_data->set_dynamic_range(dynamic_range);
probe_data->set_energy(energy);
probe_data->set_bias(bias);
+ probe_data->set_normal_bias(normal_bias);
probe_data->set_propagation(propagation);
probe_data->set_interior(interior);
probe_data->set_compress(compress);
@@ -1416,8 +1443,8 @@ PoolVector<Face3> GIProbe::get_faces(uint32_t p_usage_flags) const {
void GIProbe::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_probe_data", "data"), &GIProbe::set_probe_data);
- ClassDB::bind_method(D_METHOD("get_probe_data"), &GIProbe::get_probe_data);
+ ClassDB::bind_method(D_METHOD("set_probe_data", "data:GIProbeData"), &GIProbe::set_probe_data);
+ ClassDB::bind_method(D_METHOD("get_probe_data:GIProbeData"), &GIProbe::get_probe_data);
ClassDB::bind_method(D_METHOD("set_subdiv", "subdiv"), &GIProbe::set_subdiv);
ClassDB::bind_method(D_METHOD("get_subdiv"), &GIProbe::get_subdiv);
@@ -1434,6 +1461,9 @@ void GIProbe::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bias", "max"), &GIProbe::set_bias);
ClassDB::bind_method(D_METHOD("get_bias"), &GIProbe::get_bias);
+ ClassDB::bind_method(D_METHOD("set_normal_bias", "max"), &GIProbe::set_normal_bias);
+ ClassDB::bind_method(D_METHOD("get_normal_bias"), &GIProbe::get_normal_bias);
+
ClassDB::bind_method(D_METHOD("set_propagation", "max"), &GIProbe::set_propagation);
ClassDB::bind_method(D_METHOD("get_propagation"), &GIProbe::get_propagation);
@@ -1443,7 +1473,7 @@ void GIProbe::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_compress", "enable"), &GIProbe::set_compress);
ClassDB::bind_method(D_METHOD("is_compressed"), &GIProbe::is_compressed);
- ClassDB::bind_method(D_METHOD("bake", "from_node", "create_visual_debug"), &GIProbe::bake, DEFVAL(Variant()), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("bake", "from_node:Node", "create_visual_debug"), &GIProbe::bake, DEFVAL(Variant()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("debug_bake"), &GIProbe::_debug_bake);
ClassDB::set_method_flags(get_class_static(), _scs_create("debug_bake"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
@@ -1453,6 +1483,7 @@ void GIProbe::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::REAL, "energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_energy", "get_energy");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "propagation", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_propagation", "get_propagation");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "bias", PROPERTY_HINT_RANGE, "0,4,0.001"), "set_bias", "get_bias");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "normal_bias", PROPERTY_HINT_RANGE, "0,4,0.001"), "set_normal_bias", "get_normal_bias");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "compress"), "set_compress", "is_compressed");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "data", PROPERTY_HINT_RESOURCE_TYPE, "GIProbeData"), "set_probe_data", "get_probe_data");
@@ -1468,7 +1499,8 @@ GIProbe::GIProbe() {
subdiv = SUBDIV_128;
dynamic_range = 4;
energy = 1.0;
- bias = 1.8;
+ bias = 0.0;
+ normal_bias = 0.8;
propagation = 1.0;
extents = Vector3(10, 10, 10);
color_scan_cell_width = 4;
diff --git a/scene/3d/gi_probe.h b/scene/3d/gi_probe.h
index b5ee86455e..8346437ebd 100644
--- a/scene/3d/gi_probe.h
+++ b/scene/3d/gi_probe.h
@@ -67,6 +67,9 @@ public:
void set_bias(float p_range);
float get_bias() const;
+ void set_normal_bias(float p_range);
+ float get_normal_bias() const;
+
void set_interior(bool p_enable);
bool is_interior() const;
@@ -145,7 +148,7 @@ private:
struct PlotMesh {
Ref<Material> override_material;
Vector<Ref<Material> > instance_materials;
- Ref<ArrayMesh> mesh;
+ Ref<Mesh> mesh;
Transform local_xform;
};
@@ -163,6 +166,7 @@ private:
int dynamic_range;
float energy;
float bias;
+ float normal_bias;
float propagation;
bool interior;
bool compress;
@@ -173,7 +177,7 @@ private:
Vector<Color> _get_bake_texture(Ref<Image> p_image, const Color &p_color);
Baker::MaterialCache _get_material_cache(Ref<Material> p_material, Baker *p_baker);
void _plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 *p_vtx, const Vector2 *p_uv, const Baker::MaterialCache &p_material, const Rect3 &p_aabb, Baker *p_baker);
- void _plot_mesh(const Transform &p_xform, Ref<ArrayMesh> &p_mesh, Baker *p_baker, const Vector<Ref<Material> > &p_materials, const Ref<Material> &p_override_material);
+ void _plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, Baker *p_baker, const Vector<Ref<Material> > &p_materials, const Ref<Material> &p_override_material);
void _find_meshes(Node *p_at_node, Baker *p_baker);
void _fixup_plot(int p_idx, int p_level, int p_x, int p_y, int p_z, Baker *p_baker);
@@ -204,6 +208,9 @@ public:
void set_bias(float p_bias);
float get_bias() const;
+ void set_normal_bias(float p_normal_bias);
+ float get_normal_bias() const;
+
void set_propagation(float p_propagation);
float get_propagation() const;
diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp
index 9c87acec6e..977f1f81a7 100644
--- a/scene/3d/light.cpp
+++ b/scene/3d/light.cpp
@@ -29,7 +29,7 @@
/*************************************************************************/
#include "light.h"
-#include "global_config.h"
+#include "project_settings.h"
#include "scene/resources/surface_tool.h"
bool Light::_can_gizmo_scale() const {
diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp
index e755b1480b..51237c0bc3 100644
--- a/scene/3d/mesh_instance.cpp
+++ b/scene/3d/mesh_instance.cpp
@@ -29,9 +29,10 @@
/*************************************************************************/
#include "mesh_instance.h"
-#include "body_shape.h"
+#include "collision_shape.h"
#include "core_string_names.h"
#include "physics_body.h"
+#include "scene/resources/material.h"
#include "scene/scene_string_names.h"
#include "skeleton.h"
bool MeshInstance::_set(const StringName &p_name, const Variant &p_value) {
@@ -193,7 +194,9 @@ Node *MeshInstance::create_trimesh_collision_node() {
return NULL;
StaticBody *static_body = memnew(StaticBody);
- static_body->add_shape(shape);
+ CollisionShape *cshape = memnew(CollisionShape);
+ cshape->set_shape(shape);
+ static_body->add_child(cshape);
return static_body;
}
@@ -204,13 +207,11 @@ void MeshInstance::create_trimesh_collision() {
static_body->set_name(String(get_name()) + "_col");
add_child(static_body);
- if (get_owner())
+ if (get_owner()) {
+ CollisionShape *cshape = static_body->get_child(0)->cast_to<CollisionShape>();
static_body->set_owner(get_owner());
- CollisionShape *cshape = memnew(CollisionShape);
- cshape->set_shape(static_body->get_shape(0));
- static_body->add_child(cshape);
- if (get_owner())
cshape->set_owner(get_owner());
+ }
}
Node *MeshInstance::create_convex_collision_node() {
@@ -223,7 +224,9 @@ Node *MeshInstance::create_convex_collision_node() {
return NULL;
StaticBody *static_body = memnew(StaticBody);
- static_body->add_shape(shape);
+ CollisionShape *cshape = memnew(CollisionShape);
+ cshape->set_shape(shape);
+ static_body->add_child(cshape);
return static_body;
}
@@ -234,13 +237,11 @@ void MeshInstance::create_convex_collision() {
static_body->set_name(String(get_name()) + "_col");
add_child(static_body);
- if (get_owner())
+ if (get_owner()) {
+ CollisionShape *cshape = static_body->get_child(0)->cast_to<CollisionShape>();
static_body->set_owner(get_owner());
- CollisionShape *cshape = memnew(CollisionShape);
- cshape->set_shape(static_body->get_shape(0));
- static_body->add_child(cshape);
- if (get_owner())
cshape->set_owner(get_owner());
+ }
}
void MeshInstance::_notification(int p_what) {
@@ -274,6 +275,81 @@ void MeshInstance::_mesh_changed() {
materials.resize(mesh->get_surface_count());
}
+void MeshInstance::create_debug_tangents() {
+
+ Vector<Vector3> lines;
+ Vector<Color> colors;
+
+ Ref<Mesh> mesh = get_mesh();
+ if (!mesh.is_valid())
+ return;
+
+ for (int i = 0; i < mesh->get_surface_count(); i++) {
+ Array arrays = mesh->surface_get_arrays(i);
+ Vector<Vector3> verts = arrays[Mesh::ARRAY_VERTEX];
+ Vector<Vector3> norms = arrays[Mesh::ARRAY_NORMAL];
+ if (norms.size() == 0)
+ continue;
+ Vector<float> tangents = arrays[Mesh::ARRAY_TANGENT];
+ if (tangents.size() == 0)
+ continue;
+
+ for (int j = 0; j < verts.size(); j++) {
+ Vector3 v = verts[j];
+ Vector3 n = norms[j];
+ Vector3 t = Vector3(tangents[j * 4 + 0], tangents[j * 4 + 1], tangents[j * 4 + 2]);
+ Vector3 b = (n.cross(t)).normalized() * tangents[j * 4 + 3];
+
+ lines.push_back(v); //normal
+ colors.push_back(Color(0, 0, 1)); //color
+ lines.push_back(v + n * 0.04); //normal
+ colors.push_back(Color(0, 0, 1)); //color
+
+ lines.push_back(v); //tangent
+ colors.push_back(Color(1, 0, 0)); //color
+ lines.push_back(v + t * 0.04); //tangent
+ colors.push_back(Color(1, 0, 0)); //color
+
+ lines.push_back(v); //binormal
+ colors.push_back(Color(0, 1, 0)); //color
+ lines.push_back(v + b * 0.04); //binormal
+ colors.push_back(Color(0, 1, 0)); //color
+ }
+ }
+
+ if (lines.size()) {
+
+ Ref<SpatialMaterial> sm;
+ sm.instance();
+
+ sm->set_flag(SpatialMaterial::FLAG_UNSHADED, true);
+ sm->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true);
+ sm->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+
+ Ref<ArrayMesh> am;
+ am.instance();
+ Array a;
+ a.resize(Mesh::ARRAY_MAX);
+ a[Mesh::ARRAY_VERTEX] = lines;
+ a[Mesh::ARRAY_COLOR] = colors;
+
+ am->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a);
+ am->surface_set_material(0, sm);
+
+ MeshInstance *mi = memnew(MeshInstance);
+ mi->set_mesh(am);
+ mi->set_name("DebugTangents");
+ add_child(mi);
+#ifdef TOOLS_ENABLED
+
+ if (this == get_tree()->get_edited_scene_root())
+ mi->set_owner(this);
+ else
+ mi->set_owner(get_owner());
+#endif
+ }
+}
+
void MeshInstance::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_mesh", "mesh:Mesh"), &MeshInstance::set_mesh);
@@ -281,12 +357,18 @@ void MeshInstance::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_skeleton_path", "skeleton_path:NodePath"), &MeshInstance::set_skeleton_path);
ClassDB::bind_method(D_METHOD("get_skeleton_path:NodePath"), &MeshInstance::get_skeleton_path);
+ ClassDB::bind_method(D_METHOD("set_surface_material", "surface", "material:Material"), &MeshInstance::set_surface_material);
+ ClassDB::bind_method(D_METHOD("get_surface_material:Material", "surface"), &MeshInstance::get_surface_material);
+
ClassDB::bind_method(D_METHOD("create_trimesh_collision"), &MeshInstance::create_trimesh_collision);
ClassDB::set_method_flags("MeshInstance", "create_trimesh_collision", METHOD_FLAGS_DEFAULT);
ClassDB::bind_method(D_METHOD("create_convex_collision"), &MeshInstance::create_convex_collision);
ClassDB::set_method_flags("MeshInstance", "create_convex_collision", METHOD_FLAGS_DEFAULT);
ClassDB::bind_method(D_METHOD("_mesh_changed"), &MeshInstance::_mesh_changed);
+ ClassDB::bind_method(D_METHOD("create_debug_tangents"), &MeshInstance::create_debug_tangents);
+ ClassDB::set_method_flags("MeshInstance", "create_debug_tangents", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
+
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton"), "set_skeleton_path", "get_skeleton_path");
}
diff --git a/scene/3d/mesh_instance.h b/scene/3d/mesh_instance.h
index c11c52b76d..1bb2c97d10 100644
--- a/scene/3d/mesh_instance.h
+++ b/scene/3d/mesh_instance.h
@@ -83,6 +83,8 @@ public:
Node *create_convex_collision_node();
void create_convex_collision();
+ void create_debug_tangents();
+
virtual Rect3 get_aabb() const;
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
diff --git a/scene/3d/multimesh_instance.cpp b/scene/3d/multimesh_instance.cpp
index b51953f27c..b4558698cc 100644
--- a/scene/3d/multimesh_instance.cpp
+++ b/scene/3d/multimesh_instance.cpp
@@ -31,8 +31,8 @@
void MultiMeshInstance::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_multimesh", "multimesh"), &MultiMeshInstance::set_multimesh);
- ClassDB::bind_method(D_METHOD("get_multimesh"), &MultiMeshInstance::get_multimesh);
+ ClassDB::bind_method(D_METHOD("set_multimesh", "multimesh:MultiMesh"), &MultiMeshInstance::set_multimesh);
+ ClassDB::bind_method(D_METHOD("get_multimesh:MultiMesh"), &MultiMeshInstance::get_multimesh);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multimesh", PROPERTY_HINT_RESOURCE_TYPE, "MultiMesh"), "set_multimesh", "get_multimesh");
}
diff --git a/scene/3d/navigation_mesh.cpp b/scene/3d/navigation_mesh.cpp
index 82f6f665db..7392998d57 100644
--- a/scene/3d/navigation_mesh.cpp
+++ b/scene/3d/navigation_mesh.cpp
@@ -149,8 +149,8 @@ Ref<Mesh> NavigationMesh::get_debug_mesh() {
tw[tidx++] = f.vertex[j];
_EdgeKey ek;
- ek.from = f.vertex[j].snapped(CMP_EPSILON);
- ek.to = f.vertex[(j + 1) % 3].snapped(CMP_EPSILON);
+ ek.from = f.vertex[j].snapped(Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON));
+ ek.to = f.vertex[(j + 1) % 3].snapped(Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON));
if (ek.from < ek.to)
SWAP(ek.from, ek.to);
@@ -374,8 +374,8 @@ String NavigationMeshInstance::get_configuration_warning() const {
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_navigation_mesh", "navmesh:NavigationMesh"), &NavigationMeshInstance::set_navigation_mesh);
+ ClassDB::bind_method(D_METHOD("get_navigation_mesh:NavigationMesh"), &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);
diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp
index 2a7a804470..7e599ce2f5 100644
--- a/scene/3d/physics_body.cpp
+++ b/scene/3d/physics_body.cpp
@@ -520,11 +520,11 @@ real_t RigidBody::get_mass() const {
void RigidBody::set_weight(real_t p_weight) {
- set_mass(p_weight / 9.8);
+ set_mass(p_weight / real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8)));
}
real_t RigidBody::get_weight() const {
- return mass * 9.8;
+ return mass * real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8));
}
void RigidBody::set_friction(real_t p_friction) {
@@ -879,313 +879,105 @@ RigidBody::~RigidBody() {
//////////////////////////////////////////////////////
//////////////////////////
-Variant KinematicBody::_get_collider() const {
-
- ObjectID oid = get_collider();
- if (oid == 0)
- return Variant();
- Object *obj = ObjectDB::get_instance(oid);
- if (!obj)
- return Variant();
-
- Reference *ref = obj->cast_to<Reference>();
- if (ref) {
- return Ref<Reference>(ref);
- }
+Dictionary KinematicBody::_move(const Vector3 &p_motion) {
+
+ Collision col;
+ if (move(p_motion, col)) {
+ Dictionary d;
+ d["position"] = col.collision;
+ d["normal"] = col.collision;
+ d["local_shape"] = col.local_shape;
+ d["travel"] = col.travel;
+ d["remainder"] = col.remainder;
+ d["collider_id"] = col.collider;
+ if (col.collider) {
+ d["collider"] = ObjectDB::get_instance(col.collider);
+ } else {
+ d["collider"] = Variant();
+ }
- return obj;
-}
+ d["collider_shape_index"] = col.collider_shape;
+ d["collider_metadata"] = col.collider_metadata;
-bool KinematicBody::_ignores_mode(PhysicsServer::BodyMode p_mode) const {
+ return d;
- switch (p_mode) {
- case PhysicsServer::BODY_MODE_STATIC: return !collide_static;
- case PhysicsServer::BODY_MODE_KINEMATIC: return !collide_kinematic;
- case PhysicsServer::BODY_MODE_RIGID: return !collide_rigid;
- case PhysicsServer::BODY_MODE_CHARACTER: return !collide_character;
+ } else {
+ return Dictionary();
}
-
- return true;
}
-void KinematicBody::revert_motion() {
+bool KinematicBody::move(const Vector3 &p_motion, Collision &r_collision) {
Transform gt = get_global_transform();
- gt.origin -= travel; //I do hope this is correct.
- travel = Vector3();
- set_global_transform(gt);
-}
-
-Vector3 KinematicBody::get_travel() const {
-
- return travel;
-}
-
-Vector3 KinematicBody::move(const Vector3 &p_motion) {
-
- //give me back regular physics engine logic
- //this is madness
- //and most people using this function will think
- //what it does is simpler than using physics
- //this took about a week to get right..
- //but is it right? who knows at this point..
-
- colliding = false;
- ERR_FAIL_COND_V(!is_inside_tree(), Vector3());
- PhysicsDirectSpaceState *dss = PhysicsServer::get_singleton()->space_get_direct_state(get_world()->get_space());
- ERR_FAIL_COND_V(!dss, Vector3());
- const int max_shapes = 32;
- Vector3 sr[max_shapes * 2];
- int res_shapes;
-
- Set<RID> exclude;
- exclude.insert(get_rid());
-
- //recover first
- int recover_attempts = 4;
-
- bool collided = false;
- uint32_t mask = 0;
- if (collide_static)
- mask |= PhysicsDirectSpaceState::TYPE_MASK_STATIC_BODY;
- if (collide_kinematic)
- mask |= PhysicsDirectSpaceState::TYPE_MASK_KINEMATIC_BODY;
- if (collide_rigid)
- mask |= PhysicsDirectSpaceState::TYPE_MASK_RIGID_BODY;
- if (collide_character)
- mask |= PhysicsDirectSpaceState::TYPE_MASK_CHARACTER_BODY;
-
- //print_line("motion: "+p_motion+" margin: "+rtos(margin));
-
- //print_line("margin: "+rtos(margin));
-
- float m = margin;
- //m=0.001;
-
- do {
-
- //motion recover
- for (int i = 0; i < get_shape_count(); i++) {
-
- if (is_shape_set_as_trigger(i))
- continue;
-
- if (dss->collide_shape(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i), m, sr, max_shapes, res_shapes, exclude, get_collision_layer(), mask)) {
- collided = true;
- }
- }
-
- if (!collided)
- break;
-
- //print_line("have to recover");
- Vector3 recover_motion;
- bool all_outside = true;
- for (int j = 0; j < 8; j++) {
- for (int i = 0; i < res_shapes; i++) {
-
- Vector3 a = sr[i * 2 + 0];
- Vector3 b = sr[i * 2 + 1];
-//print_line(String()+a+" -> "+b);
-#if 0
- float d = a.distance_to(b);
-
- /*
- if (d<margin)
- continue;
- */
- recover_motion+=(b-a)*0.2;
-#else
- float dist = a.distance_to(b);
- if (dist > CMP_EPSILON) {
- Vector3 norm = (b - a).normalized();
- if (dist > margin * 0.5)
- all_outside = false;
- float adv = norm.dot(recover_motion);
- //print_line(itos(i)+" dist: "+rtos(dist)+" adv: "+rtos(adv));
- recover_motion += norm * MAX(dist - adv, 0) * 0.4;
- }
-#endif
- }
- }
-
- if (recover_motion == Vector3()) {
- collided = false;
- break;
- }
-
- //print_line("**** RECOVER: "+recover_motion);
-
- Transform gt = get_global_transform();
- gt.origin += recover_motion;
- set_global_transform(gt);
-
- recover_attempts--;
-
- if (all_outside)
- break;
-
- } while (recover_attempts);
-
- //move second
- float safe = 1.0;
- float unsafe = 1.0;
- int best_shape = -1;
-
- PhysicsDirectSpaceState::ShapeRestInfo rest;
-
- //print_line("pos: "+get_global_transform().origin);
- //print_line("motion: "+p_motion);
-
- for (int i = 0; i < get_shape_count(); i++) {
-
- if (is_shape_set_as_trigger(i))
- continue;
-
- float lsafe, lunsafe;
- PhysicsDirectSpaceState::ShapeRestInfo lrest;
- bool valid = dss->cast_motion(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i), p_motion, 0, lsafe, lunsafe, exclude, get_collision_layer(), mask, &lrest);
- //print_line("shape: "+itos(i)+" travel:"+rtos(ltravel));
- if (!valid) {
- safe = 0;
- unsafe = 0;
- best_shape = i; //sadly it's the best
- //print_line("initial stuck");
-
- break;
- }
- if (lsafe == 1.0) {
- //print_line("initial free");
- continue;
- }
- if (lsafe < safe) {
-
- //print_line("initial at "+rtos(lsafe));
- safe = lsafe;
- safe = MAX(0, lsafe - 0.01);
- unsafe = lunsafe;
- best_shape = i;
- rest = lrest;
- }
- }
-
- //print_line("best shape: "+itos(best_shape)+" motion "+p_motion);
-
- if (safe >= 1) {
- //not collided
- colliding = false;
- } else {
-
- colliding = true;
-
- if (true || (safe == 0 && unsafe == 0)) { //use it always because it's more precise than GJK
- //no advance, use rest info from collision
- Transform ugt = get_global_transform();
- ugt.origin += p_motion * unsafe;
-
- PhysicsDirectSpaceState::ShapeRestInfo rest_info;
- bool c2 = dss->rest_info(get_shape(best_shape)->get_rid(), ugt * get_shape_transform(best_shape), m, &rest, exclude, get_collision_layer(), mask);
- if (!c2) {
- //should not happen, but floating point precision is so weird..
- colliding = false;
- }
-
- //print_line("Rest Travel: "+rest.normal);
- }
-
- if (colliding) {
-
- collision = rest.point;
- normal = rest.normal;
- collider = rest.collider_id;
- collider_vel = rest.linear_velocity;
- collider_shape = rest.shape;
- }
+ PhysicsServer::MotionResult result;
+ bool colliding = PhysicsServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, margin, &result);
+
+ if (colliding) {
+ r_collision.collider_metadata = result.collider_metadata;
+ r_collision.collider_shape = result.collider_shape;
+ r_collision.collider_vel = result.collider_velocity;
+ r_collision.collision = result.collision_point;
+ r_collision.normal = result.collision_normal;
+ r_collision.collider = result.collider_id;
+ r_collision.travel = result.motion;
+ r_collision.remainder = result.remainder;
+ r_collision.local_shape = result.collision_local_shape;
}
- Vector3 motion = p_motion * safe;
- /*
- if (colliding)
- motion+=normal*0.001;
- */
- Transform gt = get_global_transform();
- gt.origin += motion;
+ gt.origin += result.motion;
set_global_transform(gt);
- travel = motion;
- return p_motion - motion;
+ return colliding;
}
-Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction, const Vector3 &p_ceil_direction, float p_slope_stop_min_velocity, int p_max_bounces, float p_floor_max_angle, float p_ceil_max_angle) {
+Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction, float p_slope_stop_min_velocity, int p_max_bounces, float p_floor_max_angle) {
- /*
- Things to note:
- 1. This function is basically the KinematicBody2D function ported over.
- 2. The 'travel' variable and stuff relating to it exists more or less for this function's sake.
- 3. Someone is going to have to document this, so here's an example for them:
- vel = move_and_slide(vel, Vector3(0, 1, 0), Vector3(0, -1, 0), 0.1);
- Very useful for FPS controllers so long as you control horizontal motion properly - even for Quake-style AABB colliders.
- The slope stop system is... rather weird, and it's correct operation depends on what scale your game is built on,
- but as far as I can tell in theory it's suppposed to be a way of turning impassable slopes into invisible walls.
- It can also be a pain, since there's a better-known way of defining such things: "let gravity do the work".
- If you don't like it, set it to positive infinity.
- 4. Might be a bug somewhere else in physics: When there are two CollisionShape nodes with a shared Shape, only one is considered, I think.
- Test this further.
- */
-
- Vector3 motion = (move_and_slide_floor_velocity + p_linear_velocity) * get_fixed_process_delta_time();
+ Vector3 motion = (floor_velocity + p_linear_velocity) * get_fixed_process_delta_time();
Vector3 lv = p_linear_velocity;
- move_and_slide_on_floor = false;
- move_and_slide_on_ceiling = false;
- move_and_slide_on_wall = false;
- move_and_slide_colliders.clear();
- move_and_slide_floor_velocity = Vector3();
+ on_floor = false;
+ on_ceiling = false;
+ on_wall = false;
+ colliders.clear();
+ floor_velocity = Vector3();
while (p_max_bounces) {
- motion = move(motion);
+ Collision collision;
- if (is_colliding()) {
+ bool collided = move(motion, collision);
- bool hit_horizontal = false; //hit floor or ceiling
+ if (collided) {
- if (p_floor_direction != Vector3()) {
- if (get_collision_normal().dot(p_floor_direction) >= Math::cos(p_floor_max_angle)) { //floor
+ motion = collision.remainder;
- hit_horizontal = true;
- move_and_slide_on_floor = true;
- move_and_slide_floor_velocity = get_collider_velocity();
+ if (p_floor_direction == Vector3()) {
+ //all is a wall
+ on_wall = true;
+ } else {
+ if (collision.normal.dot(p_floor_direction) >= Math::cos(p_floor_max_angle)) { //floor
- //Note: These two lines are the only lines that really changed between 3D/2D, see if it can't be reused somehow???
- Vector2 hz_velocity = Vector2(lv.x - move_and_slide_floor_velocity.x, lv.z - move_and_slide_floor_velocity.z);
- if (get_travel().length() < 1 && hz_velocity.length() < p_slope_stop_min_velocity) {
- revert_motion();
- return Vector3();
- }
- }
- }
+ on_floor = true;
+ floor_velocity = collision.collider_vel;
- if (p_ceil_direction != Vector3()) {
- if (get_collision_normal().dot(p_ceil_direction) >= Math::cos(p_ceil_max_angle)) { //ceiling
- hit_horizontal = true;
- move_and_slide_on_ceiling = true;
+ /*if (collision.travel.length() < 0.01 && ABS((lv.x - floor_velocity.x)) < p_slope_stop_min_velocity) {
+ Transform gt = get_global_transform();
+ gt.elements[2] -= collision.travel;
+ set_global_transform(gt);
+ return Vector3();
+ }*/
+ } else if (collision.normal.dot(-p_floor_direction) >= Math::cos(p_floor_max_angle)) { //ceiling
+ on_ceiling = true;
+ } else {
+ on_wall = true;
}
}
- //if it hit something but didn't hit a floor or ceiling, it is by default a wall
- //(this imitates the pre-specifiable-ceiling logic more or less, except ceiling is optional)
- if (!hit_horizontal) {
- move_and_slide_on_wall = true;
- }
-
- Vector3 n = get_collision_normal();
+ Vector3 n = collision.normal;
motion = motion.slide(n);
lv = lv.slide(n);
- Variant collider = _get_collider();
- if (collider.get_type() != Variant::NIL) {
- move_and_slide_colliders.push_back(collider);
- }
+
+ colliders.push_back(collision);
} else {
break;
@@ -1199,199 +991,148 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve
return lv;
}
-bool KinematicBody::is_move_and_slide_on_floor() const {
-
- return move_and_slide_on_floor;
-}
-bool KinematicBody::is_move_and_slide_on_wall() const {
+bool KinematicBody::is_on_floor() const {
- return move_and_slide_on_wall;
+ return on_floor;
}
-bool KinematicBody::is_move_and_slide_on_ceiling() const {
+bool KinematicBody::is_on_wall() const {
- return move_and_slide_on_ceiling;
+ return on_wall;
}
-Array KinematicBody::get_move_and_slide_colliders() const {
+bool KinematicBody::is_on_ceiling() const {
- return move_and_slide_colliders;
+ return on_ceiling;
}
-Vector3 KinematicBody::move_to(const Vector3 &p_position) {
+Vector3 KinematicBody::get_floor_velocity() const {
- return move(p_position - get_global_transform().origin);
+ return floor_velocity;
}
-bool KinematicBody::can_teleport_to(const Vector3 &p_position) {
+bool KinematicBody::test_move(const Transform &p_from, const Vector3 &p_motion) {
ERR_FAIL_COND_V(!is_inside_tree(), false);
- PhysicsDirectSpaceState *dss = PhysicsServer::get_singleton()->space_get_direct_state(get_world()->get_space());
- ERR_FAIL_COND_V(!dss, false);
-
- uint32_t mask = 0;
- if (collide_static)
- mask |= PhysicsDirectSpaceState::TYPE_MASK_STATIC_BODY;
- if (collide_kinematic)
- mask |= PhysicsDirectSpaceState::TYPE_MASK_KINEMATIC_BODY;
- if (collide_rigid)
- mask |= PhysicsDirectSpaceState::TYPE_MASK_RIGID_BODY;
- if (collide_character)
- mask |= PhysicsDirectSpaceState::TYPE_MASK_CHARACTER_BODY;
-
- Transform xform = get_global_transform();
- xform.origin = p_position;
-
- Set<RID> exclude;
- exclude.insert(get_rid());
-
- for (int i = 0; i < get_shape_count(); i++) {
-
- if (is_shape_set_as_trigger(i))
- continue;
-
- bool col = dss->intersect_shape(get_shape(i)->get_rid(), xform * get_shape_transform(i), 0, NULL, 1, exclude, get_collision_layer(), mask);
- if (col)
- return false;
- }
- return true;
+ return PhysicsServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, margin);
}
-bool KinematicBody::is_colliding() const {
+void KinematicBody::set_safe_margin(float p_margin) {
- ERR_FAIL_COND_V(!is_inside_tree(), false);
-
- return colliding;
+ margin = p_margin;
}
-Vector3 KinematicBody::get_collision_pos() const {
- ERR_FAIL_COND_V(!colliding, Vector3());
- return collision;
-}
-Vector3 KinematicBody::get_collision_normal() const {
+float KinematicBody::get_safe_margin() const {
- ERR_FAIL_COND_V(!colliding, Vector3());
- return normal;
+ return margin;
}
-Vector3 KinematicBody::get_collider_velocity() const {
+int KinematicBody::get_collision_count() const {
- return collider_vel;
+ return colliders.size();
}
+Vector3 KinematicBody::get_collision_position(int p_collision) const {
-ObjectID KinematicBody::get_collider() const {
-
- ERR_FAIL_COND_V(!colliding, 0);
- return collider;
-}
-int KinematicBody::get_collider_shape() const {
+ ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector3());
- ERR_FAIL_COND_V(!colliding, -1);
- return collider_shape;
+ return colliders[p_collision].collision;
}
-void KinematicBody::set_collide_with_static_bodies(bool p_enable) {
-
- collide_static = p_enable;
+Vector3 KinematicBody::get_collision_normal(int p_collision) const {
+ ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector3());
+ return colliders[p_collision].normal;
}
-bool KinematicBody::can_collide_with_static_bodies() const {
- return collide_static;
+Vector3 KinematicBody::get_collision_travel(int p_collision) const {
+ ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector3());
+ return colliders[p_collision].travel;
}
-
-void KinematicBody::set_collide_with_rigid_bodies(bool p_enable) {
-
- collide_rigid = p_enable;
+Vector3 KinematicBody::get_collision_remainder(int p_collision) const {
+ ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector3());
+ return colliders[p_collision].remainder;
}
-bool KinematicBody::can_collide_with_rigid_bodies() const {
-
- return collide_rigid;
+Object *KinematicBody::get_collision_local_shape(int p_collision) const {
+ ERR_FAIL_INDEX_V(p_collision, colliders.size(), NULL);
+ uint32_t owner = shape_find_owner(colliders[p_collision].local_shape);
+ return shape_owner_get_owner(owner);
}
+Object *KinematicBody::get_collision_collider(int p_collision) const {
+ ERR_FAIL_INDEX_V(p_collision, colliders.size(), NULL);
-void KinematicBody::set_collide_with_kinematic_bodies(bool p_enable) {
+ if (colliders[p_collision].collider) {
+ return ObjectDB::get_instance(colliders[p_collision].collider);
+ }
- collide_kinematic = p_enable;
+ return NULL;
}
-bool KinematicBody::can_collide_with_kinematic_bodies() const {
+ObjectID KinematicBody::get_collision_collider_id(int p_collision) const {
+ ERR_FAIL_INDEX_V(p_collision, colliders.size(), 0);
- return collide_kinematic;
+ return colliders[p_collision].collider;
}
+Object *KinematicBody::get_collision_collider_shape(int p_collision) const {
+ ERR_FAIL_INDEX_V(p_collision, colliders.size(), NULL);
+ Object *collider = get_collision_collider(p_collision);
+ if (collider) {
+ CollisionObject *obj2d = collider->cast_to<CollisionObject>();
+ if (obj2d) {
+ uint32_t owner = shape_find_owner(colliders[p_collision].collider_shape);
+ return obj2d->shape_owner_get_owner(owner);
+ }
+ }
-void KinematicBody::set_collide_with_character_bodies(bool p_enable) {
-
- collide_character = p_enable;
+ return NULL;
}
-bool KinematicBody::can_collide_with_character_bodies() const {
-
- return collide_character;
+int KinematicBody::get_collision_collider_shape_index(int p_collision) const {
+ ERR_FAIL_INDEX_V(p_collision, colliders.size(), -1);
+ return colliders[p_collision].collider_shape;
}
-
-void KinematicBody::set_collision_margin(float p_margin) {
-
- margin = p_margin;
+Vector3 KinematicBody::get_collision_collider_velocity(int p_collision) const {
+ ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector3());
+ return colliders[p_collision].collider_vel;
}
-
-float KinematicBody::get_collision_margin() const {
-
- return margin;
+Variant KinematicBody::get_collision_collider_metadata(int p_collision) const {
+ ERR_FAIL_INDEX_V(p_collision, colliders.size(), Variant());
+ return colliders[p_collision].collider_metadata;
}
void KinematicBody::_bind_methods() {
- ClassDB::bind_method(D_METHOD("move", "rel_vec"), &KinematicBody::move);
- ClassDB::bind_method(D_METHOD("move_to", "position"), &KinematicBody::move_to);
- ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "ceil_normal", "slope_stop_min_velocity", "max_bounces", "floor_max_angle", "ceil_max_angle"), &KinematicBody::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(Vector3(0, 0, 0)), DEFVAL(5), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(Math::deg2rad((float)45)));
-
- ClassDB::bind_method(D_METHOD("can_teleport_to", "position"), &KinematicBody::can_teleport_to);
+ ClassDB::bind_method(D_METHOD("move", "rel_vec"), &KinematicBody::_move);
+ ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "slope_stop_min_velocity", "max_bounces", "floor_max_angle"), &KinematicBody::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(0.05), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)));
- ClassDB::bind_method(D_METHOD("is_colliding"), &KinematicBody::is_colliding);
+ ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec"), &KinematicBody::test_move);
- ClassDB::bind_method(D_METHOD("get_collision_pos"), &KinematicBody::get_collision_pos);
- ClassDB::bind_method(D_METHOD("get_collision_normal"), &KinematicBody::get_collision_normal);
- ClassDB::bind_method(D_METHOD("get_collider_velocity"), &KinematicBody::get_collider_velocity);
- ClassDB::bind_method(D_METHOD("get_collider:Variant"), &KinematicBody::_get_collider);
- ClassDB::bind_method(D_METHOD("get_collider_shape"), &KinematicBody::get_collider_shape);
+ 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_velocity"), &KinematicBody::get_floor_velocity);
- ClassDB::bind_method(D_METHOD("set_collide_with_static_bodies", "enable"), &KinematicBody::set_collide_with_static_bodies);
- ClassDB::bind_method(D_METHOD("can_collide_with_static_bodies"), &KinematicBody::can_collide_with_static_bodies);
+ ClassDB::bind_method(D_METHOD("set_safe_margin", "pixels"), &KinematicBody::set_safe_margin);
+ ClassDB::bind_method(D_METHOD("get_safe_margin", "pixels"), &KinematicBody::get_safe_margin);
- ClassDB::bind_method(D_METHOD("set_collide_with_kinematic_bodies", "enable"), &KinematicBody::set_collide_with_kinematic_bodies);
- ClassDB::bind_method(D_METHOD("can_collide_with_kinematic_bodies"), &KinematicBody::can_collide_with_kinematic_bodies);
+ ClassDB::bind_method(D_METHOD("get_collision_count"), &KinematicBody::get_collision_count);
+ ClassDB::bind_method(D_METHOD("get_collision_position", "collision"), &KinematicBody::get_collision_position);
+ ClassDB::bind_method(D_METHOD("get_collision_normal", "collision"), &KinematicBody::get_collision_normal);
+ ClassDB::bind_method(D_METHOD("get_collision_travel", "collision"), &KinematicBody::get_collision_travel);
+ ClassDB::bind_method(D_METHOD("get_collision_remainder", "collision"), &KinematicBody::get_collision_remainder);
+ ClassDB::bind_method(D_METHOD("get_collision_local_shape", "collision"), &KinematicBody::get_collision_local_shape);
+ ClassDB::bind_method(D_METHOD("get_collision_collider", "collision"), &KinematicBody::get_collision_collider);
+ ClassDB::bind_method(D_METHOD("get_collision_collider_id", "collision"), &KinematicBody::get_collision_collider_id);
+ ClassDB::bind_method(D_METHOD("get_collision_collider_shape", "collision"), &KinematicBody::get_collision_collider_shape);
+ ClassDB::bind_method(D_METHOD("get_collision_collider_shape_index", "collision"), &KinematicBody::get_collision_collider_shape_index);
+ ClassDB::bind_method(D_METHOD("get_collision_collider_velocity", "collision"), &KinematicBody::get_collision_collider_velocity);
+ ClassDB::bind_method(D_METHOD("get_collision_collider_metadata", "collision"), &KinematicBody::get_collision_collider_metadata);
- ClassDB::bind_method(D_METHOD("set_collide_with_rigid_bodies", "enable"), &KinematicBody::set_collide_with_rigid_bodies);
- ClassDB::bind_method(D_METHOD("can_collide_with_rigid_bodies"), &KinematicBody::can_collide_with_rigid_bodies);
-
- ClassDB::bind_method(D_METHOD("set_collide_with_character_bodies", "enable"), &KinematicBody::set_collide_with_character_bodies);
- ClassDB::bind_method(D_METHOD("can_collide_with_character_bodies"), &KinematicBody::can_collide_with_character_bodies);
-
- ClassDB::bind_method(D_METHOD("set_collision_margin", "pixels"), &KinematicBody::set_collision_margin);
- ClassDB::bind_method(D_METHOD("get_collision_margin", "pixels"), &KinematicBody::get_collision_margin);
-
- ClassDB::bind_method(D_METHOD("get_travel"), &KinematicBody::get_travel);
- ClassDB::bind_method(D_METHOD("revert_motion"), &KinematicBody::revert_motion);
-
- ClassDB::bind_method(D_METHOD("get_move_and_slide_colliders"), &KinematicBody::get_move_and_slide_colliders);
- ClassDB::bind_method(D_METHOD("is_move_and_slide_on_floor"), &KinematicBody::is_move_and_slide_on_floor);
- ClassDB::bind_method(D_METHOD("is_move_and_slide_on_ceiling"), &KinematicBody::is_move_and_slide_on_ceiling);
- ClassDB::bind_method(D_METHOD("is_move_and_slide_on_wall"), &KinematicBody::is_move_and_slide_on_wall);
-
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with/static"), "set_collide_with_static_bodies", "can_collide_with_static_bodies");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with/kinematic"), "set_collide_with_kinematic_bodies", "can_collide_with_kinematic_bodies");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with/rigid"), "set_collide_with_rigid_bodies", "can_collide_with_rigid_bodies");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with/character"), "set_collide_with_character_bodies", "can_collide_with_character_bodies");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "collision/margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_collision_margin", "get_collision_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin");
}
KinematicBody::KinematicBody()
: PhysicsBody(PhysicsServer::BODY_MODE_KINEMATIC) {
- collide_static = true;
- collide_rigid = true;
- collide_kinematic = true;
- collide_character = true;
-
- colliding = false;
- collider = 0;
margin = 0.001;
- collider_shape = 0;
+
+ on_floor = false;
+ on_ceiling = false;
+ on_wall = false;
}
KinematicBody::~KinematicBody() {
}
diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h
index db4147f8f6..f86d7d957f 100644
--- a/scene/3d/physics_body.h
+++ b/scene/3d/physics_body.h
@@ -263,75 +263,60 @@ class KinematicBody : public PhysicsBody {
GDCLASS(KinematicBody, PhysicsBody);
- float margin;
- bool collide_static;
- bool collide_rigid;
- bool collide_kinematic;
- bool collide_character;
-
- bool colliding;
- Vector3 collision;
- Vector3 normal;
- Vector3 collider_vel;
- ObjectID collider;
- int collider_shape;
- Vector3 travel;
-
- Vector3 move_and_slide_floor_velocity;
- bool move_and_slide_on_floor;
- bool move_and_slide_on_ceiling;
- bool move_and_slide_on_wall;
- Array move_and_slide_colliders;
-
- Variant _get_collider() const;
-
- _FORCE_INLINE_ bool _ignores_mode(PhysicsServer::BodyMode) const;
-
-protected:
- static void _bind_methods();
-
public:
- enum {
- SLIDE_FLAG_FLOOR,
- SLIDE_FLAG_WALL,
- SLIDE_FLAG_ROOF
+ struct Collision {
+ Vector3 collision;
+ Vector3 normal;
+ Vector3 collider_vel;
+ ObjectID collider;
+ int collider_shape;
+ Variant collider_metadata;
+ Vector3 remainder;
+ Vector3 travel;
+ int local_shape;
};
- Vector3 move(const Vector3 &p_motion);
- Vector3 move_to(const Vector3 &p_position);
-
- bool can_teleport_to(const Vector3 &p_position);
- bool is_colliding() const;
-
- Vector3 get_travel() const; // Set by move and others. Consider unreliable except immediately after a move call.
- void revert_motion();
-
- Vector3 get_collision_pos() const;
- Vector3 get_collision_normal() const;
- Vector3 get_collider_velocity() const;
- ObjectID get_collider() const;
- int get_collider_shape() const;
-
- void set_collide_with_static_bodies(bool p_enable);
- bool can_collide_with_static_bodies() const;
+private:
+ float margin;
- void set_collide_with_rigid_bodies(bool p_enable);
- bool can_collide_with_rigid_bodies() const;
+ Vector3 floor_velocity;
+ bool on_floor;
+ bool on_ceiling;
+ bool on_wall;
+ Vector<Collision> colliders;
- void set_collide_with_kinematic_bodies(bool p_enable);
- bool can_collide_with_kinematic_bodies() const;
+ _FORCE_INLINE_ bool _ignores_mode(PhysicsServer::BodyMode) const;
- void set_collide_with_character_bodies(bool p_enable);
- bool can_collide_with_character_bodies() const;
+ Dictionary _move(const Vector3 &p_motion);
- void set_collision_margin(float p_margin);
- float get_collision_margin() const;
+protected:
+ static void _bind_methods();
- Vector3 move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction = Vector3(0, 0, 0), const Vector3 &p_ceil_direction = Vector3(0, 0, 0), float p_slope_stop_min_velocity = 5, int p_max_bounces = 4, float p_floor_max_angle = Math::deg2rad((float)45), float p_ceil_max_angle = Math::deg2rad((float)45));
- bool is_move_and_slide_on_floor() const;
- bool is_move_and_slide_on_wall() const;
- bool is_move_and_slide_on_ceiling() const;
- Array get_move_and_slide_colliders() const;
+public:
+ bool move(const Vector3 &p_motion, Collision &r_collision);
+ bool test_move(const Transform &p_from, const Vector3 &p_motion);
+
+ 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), float p_slope_stop_min_velocity = 0.05, int p_max_bounces = 4, float p_floor_max_angle = Math::deg2rad((float)45));
+ bool is_on_floor() const;
+ bool is_on_wall() const;
+ bool is_on_ceiling() const;
+ Vector3 get_floor_velocity() const;
+
+ int get_collision_count() const;
+ Vector3 get_collision_position(int p_collision) const;
+ Vector3 get_collision_normal(int p_collision) const;
+ Vector3 get_collision_travel(int p_collision) const;
+ Vector3 get_collision_remainder(int p_collision) const;
+ Object *get_collision_local_shape(int p_collision) const;
+ Object *get_collision_collider(int p_collision) const;
+ ObjectID get_collision_collider_id(int p_collision) const;
+ Object *get_collision_collider_shape(int p_collision) const;
+ int get_collision_collider_shape_index(int p_collision) const;
+ Vector3 get_collision_collider_velocity(int p_collision) const;
+ Variant get_collision_collider_metadata(int p_collision) const;
KinematicBody();
~KinematicBody();
diff --git a/scene/3d/portal.cpp b/scene/3d/portal.cpp
index 64a9dc14ab..d77dde1dd8 100644
--- a/scene/3d/portal.cpp
+++ b/scene/3d/portal.cpp
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "portal.h"
-#include "global_config.h"
+#include "project_settings.h"
#include "scene/resources/surface_tool.h"
#include "servers/visual_server.h"
diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp
index 86a62bec97..0dc5b58e45 100644
--- a/scene/3d/reflection_probe.cpp
+++ b/scene/3d/reflection_probe.cpp
@@ -162,7 +162,7 @@ bool ReflectionProbe::are_shadows_enabled() const {
void ReflectionProbe::set_cull_mask(uint32_t p_layers) {
cull_mask = p_layers;
- VS::get_singleton()->reflection_probe_set_enable_shadows(probe, p_layers);
+ VS::get_singleton()->reflection_probe_set_cull_mask(probe, p_layers);
}
uint32_t ReflectionProbe::get_cull_mask() const {
diff --git a/scene/3d/remote_transform.cpp b/scene/3d/remote_transform.cpp
index b36f444bea..4dcfb5f94e 100644
--- a/scene/3d/remote_transform.cpp
+++ b/scene/3d/remote_transform.cpp
@@ -63,7 +63,45 @@ void RemoteTransform::_update_remote() {
return;
//todo make faster
- n->set_global_transform(get_global_transform());
+ if (use_global_coordinates) {
+
+ if (update_remote_position && update_remote_rotation && update_remote_scale) {
+ n->set_global_transform(get_global_transform());
+ } else {
+ Transform n_trans = n->get_global_transform();
+ Transform our_trans = get_global_transform();
+
+ if (!update_remote_position)
+ our_trans.set_origin(n_trans.get_origin());
+
+ n->set_global_transform(our_trans);
+
+ if (!update_remote_rotation)
+ n->set_rotation(n_trans.basis.get_rotation());
+
+ if (!update_remote_scale)
+ n->set_scale(n_trans.basis.get_scale());
+ }
+
+ } else {
+ if (update_remote_position && update_remote_rotation && update_remote_scale) {
+ n->set_global_transform(get_global_transform());
+ } else {
+ Transform n_trans = n->get_transform();
+ Transform our_trans = get_transform();
+
+ if (!update_remote_position)
+ our_trans.set_origin(n_trans.get_origin());
+
+ n->set_transform(our_trans);
+
+ if (!update_remote_rotation)
+ n->set_rotation(n_trans.basis.get_rotation());
+
+ if (!update_remote_scale)
+ n->set_scale(n_trans.basis.get_scale());
+ }
+ }
}
void RemoteTransform::_notification(int p_what) {
@@ -102,6 +140,41 @@ NodePath RemoteTransform::get_remote_node() const {
return remote_node;
}
+void RemoteTransform::set_use_global_coordinates(const bool p_enable) {
+ use_global_coordinates = p_enable;
+}
+
+bool RemoteTransform::get_use_global_coordinates() const {
+ return use_global_coordinates;
+}
+
+void RemoteTransform::set_update_position(const bool p_update) {
+ update_remote_position = p_update;
+ _update_remote();
+}
+
+bool RemoteTransform::get_update_position() const {
+ return update_remote_position;
+}
+
+void RemoteTransform::set_update_rotation(const bool p_update) {
+ update_remote_rotation = p_update;
+ _update_remote();
+}
+
+bool RemoteTransform::get_update_rotation() const {
+ return update_remote_rotation;
+}
+
+void RemoteTransform::set_update_scale(const bool p_update) {
+ update_remote_scale = p_update;
+ _update_remote();
+}
+
+bool RemoteTransform::get_update_scale() const {
+ return update_remote_scale;
+}
+
String RemoteTransform::get_configuration_warning() const {
if (!has_node(remote_node) || !get_node(remote_node) || !get_node(remote_node)->cast_to<Spatial>()) {
@@ -116,11 +189,32 @@ void RemoteTransform::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_remote_node", "path"), &RemoteTransform::set_remote_node);
ClassDB::bind_method(D_METHOD("get_remote_node"), &RemoteTransform::get_remote_node);
+ ClassDB::bind_method(D_METHOD("set_use_global_coordinates", "use_global_coordinates"), &RemoteTransform::set_use_global_coordinates);
+ ClassDB::bind_method(D_METHOD("get_use_global_coordinates"), &RemoteTransform::get_use_global_coordinates);
+
+ ClassDB::bind_method(D_METHOD("set_update_position", "update_remote_position"), &RemoteTransform::set_update_position);
+ ClassDB::bind_method(D_METHOD("get_update_position"), &RemoteTransform::get_update_position);
+ ClassDB::bind_method(D_METHOD("set_update_rotation", "update_remote_rotation"), &RemoteTransform::set_update_rotation);
+ ClassDB::bind_method(D_METHOD("get_update_rotation"), &RemoteTransform::get_update_rotation);
+ ClassDB::bind_method(D_METHOD("set_update_scale", "update_remote_scale"), &RemoteTransform::set_update_scale);
+ ClassDB::bind_method(D_METHOD("get_update_scale"), &RemoteTransform::get_update_scale);
+
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "remote_path"), "set_remote_node", "get_remote_node");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_global_coordinates"), "set_use_global_coordinates", "get_use_global_coordinates");
+
+ ADD_GROUP("Update", "update_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_position"), "set_update_position", "get_update_position");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_rotation"), "set_update_rotation", "get_update_rotation");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_scale"), "set_update_scale", "get_update_scale");
}
RemoteTransform::RemoteTransform() {
+ use_global_coordinates = true;
+ update_remote_position = true;
+ update_remote_rotation = true;
+ update_remote_scale = true;
+
cache = 0;
set_notify_transform(true);
}
diff --git a/scene/3d/remote_transform.h b/scene/3d/remote_transform.h
index 9fa3011185..c25b57966e 100644
--- a/scene/3d/remote_transform.h
+++ b/scene/3d/remote_transform.h
@@ -39,6 +39,11 @@ class RemoteTransform : public Spatial {
ObjectID cache;
+ bool use_global_coordinates;
+ bool update_remote_position;
+ bool update_remote_rotation;
+ bool update_remote_scale;
+
void _update_remote();
void _update_cache();
@@ -50,6 +55,18 @@ public:
void set_remote_node(const NodePath &p_remote_node);
NodePath get_remote_node() const;
+ void set_use_global_coordinates(const bool p_enable);
+ bool get_use_global_coordinates() const;
+
+ void set_update_position(const bool p_update);
+ bool get_update_position() const;
+
+ void set_update_rotation(const bool p_update);
+ bool get_update_rotation() const;
+
+ void set_update_scale(const bool p_update);
+ bool get_update_scale() const;
+
virtual String get_configuration_warning() const;
RemoteTransform();
diff --git a/scene/3d/room_instance.cpp b/scene/3d/room_instance.cpp
index 85713cf43a..7827768c09 100644
--- a/scene/3d/room_instance.cpp
+++ b/scene/3d/room_instance.cpp
@@ -32,7 +32,7 @@
#include "servers/visual_server.h"
#include "geometry.h"
-#include "global_config.h"
+#include "project_settings.h"
#include "scene/resources/surface_tool.h"
void Room::_notification(int p_what) {
diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp
index d498947a41..71af77c027 100644
--- a/scene/3d/skeleton.cpp
+++ b/scene/3d/skeleton.cpp
@@ -31,7 +31,7 @@
#include "message_queue.h"
-#include "core/global_config.h"
+#include "core/project_settings.h"
#include "scene/resources/surface_tool.h"
bool Skeleton::_set(const StringName &p_path, const Variant &p_value) {
diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp
index 3debbf02c3..6106b0904a 100644
--- a/scene/3d/spatial.cpp
+++ b/scene/3d/spatial.cpp
@@ -541,10 +541,7 @@ void Spatial::show() {
if (!is_inside_tree())
return;
- if (!data.parent || is_visible_in_tree()) {
-
- _propagate_visibility_changed();
- }
+ _propagate_visibility_changed();
}
void Spatial::hide() {
@@ -552,14 +549,14 @@ void Spatial::hide() {
if (!data.visible)
return;
- bool was_visible = is_visible_in_tree();
data.visible = false;
- if (!data.parent || was_visible) {
+ if (!is_inside_tree())
+ return;
- _propagate_visibility_changed();
- }
+ _propagate_visibility_changed();
}
+
bool Spatial::is_visible_in_tree() const {
const Spatial *s = this;
@@ -677,6 +674,16 @@ void Spatial::look_at_from_pos(const Vector3 &p_pos, const Vector3 &p_target, co
set_global_transform(lookat);
}
+Vector3 Spatial::to_local(Vector3 p_global) const {
+
+ return get_global_transform().affine_inverse().xform(p_global);
+}
+
+Vector3 Spatial::to_global(Vector3 p_local) const {
+
+ return get_global_transform().xform(p_local);
+}
+
void Spatial::set_notify_transform(bool p_enable) {
data.notify_transform = p_enable;
}
@@ -707,7 +714,7 @@ void Spatial::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_scale"), &Spatial::get_scale);
ClassDB::bind_method(D_METHOD("set_global_transform", "global"), &Spatial::set_global_transform);
ClassDB::bind_method(D_METHOD("get_global_transform"), &Spatial::get_global_transform);
- ClassDB::bind_method(D_METHOD("get_parent_spatial"), &Spatial::get_parent_spatial);
+ ClassDB::bind_method(D_METHOD("get_parent_spatial:Spatial"), &Spatial::get_parent_spatial);
ClassDB::bind_method(D_METHOD("set_ignore_transform_notification", "enabled"), &Spatial::set_ignore_transform_notification);
ClassDB::bind_method(D_METHOD("set_as_toplevel", "enable"), &Spatial::set_as_toplevel);
ClassDB::bind_method(D_METHOD("is_set_as_toplevel"), &Spatial::is_set_as_toplevel);
@@ -725,7 +732,7 @@ void Spatial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_gizmo", "gizmo:SpatialGizmo"), &Spatial::set_gizmo);
ClassDB::bind_method(D_METHOD("get_gizmo:SpatialGizmo"), &Spatial::get_gizmo);
- ClassDB::bind_method(D_METHOD("set_visible"), &Spatial::set_visible);
+ ClassDB::bind_method(D_METHOD("set_visible", "visible"), &Spatial::set_visible);
ClassDB::bind_method(D_METHOD("is_visible"), &Spatial::is_visible);
ClassDB::bind_method(D_METHOD("is_visible_in_tree"), &Spatial::is_visible_in_tree);
ClassDB::bind_method(D_METHOD("show"), &Spatial::show);
@@ -759,6 +766,9 @@ void Spatial::_bind_methods() {
ClassDB::bind_method(D_METHOD("look_at", "target", "up"), &Spatial::look_at);
ClassDB::bind_method(D_METHOD("look_at_from_pos", "pos", "target", "up"), &Spatial::look_at_from_pos);
+ ClassDB::bind_method(D_METHOD("to_local", "global_point"), &Spatial::to_local);
+ ClassDB::bind_method(D_METHOD("to_global", "local_point"), &Spatial::to_global);
+
BIND_CONSTANT(NOTIFICATION_TRANSFORM_CHANGED);
BIND_CONSTANT(NOTIFICATION_ENTER_WORLD);
BIND_CONSTANT(NOTIFICATION_EXIT_WORLD);
diff --git a/scene/3d/spatial.h b/scene/3d/spatial.h
index d114a6231b..f22b19d3cc 100644
--- a/scene/3d/spatial.h
+++ b/scene/3d/spatial.h
@@ -173,6 +173,9 @@ public:
void look_at(const Vector3 &p_target, const Vector3 &p_up_normal);
void look_at_from_pos(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up_normal);
+ Vector3 to_local(Vector3 p_global) const;
+ Vector3 to_global(Vector3 p_local) const;
+
void set_notify_transform(bool p_enable);
bool is_transform_notification_enabled() const;
diff --git a/scene/3d/spatial_velocity_tracker.cpp b/scene/3d/spatial_velocity_tracker.cpp
new file mode 100644
index 0000000000..dc822d0446
--- /dev/null
+++ b/scene/3d/spatial_velocity_tracker.cpp
@@ -0,0 +1,104 @@
+#include "spatial_velocity_tracker.h"
+#include "engine.h"
+
+void SpatialVelocityTracker::set_track_fixed_step(bool p_track_fixed_step) {
+
+ fixed_step = p_track_fixed_step;
+}
+
+bool SpatialVelocityTracker::is_tracking_fixed_step() const {
+
+ return fixed_step;
+}
+void SpatialVelocityTracker::update_position(const Vector3 &p_position) {
+
+ PositionHistory ph;
+ ph.position = p_position;
+ if (fixed_step) {
+ ph.frame = Engine::get_singleton()->get_fixed_frames();
+ } else {
+ ph.frame = Engine::get_singleton()->get_idle_frame_ticks();
+ }
+
+ if (position_history_len == 0 || position_history[0].frame != ph.frame) { //in same frame, use latest
+ position_history_len = MIN(position_history.size(), position_history_len + 1);
+ for (int i = position_history_len - 1; i > 0; i--) {
+ position_history[i] = position_history[i - 1];
+ }
+ }
+
+ position_history[0] = ph;
+}
+Vector3 SpatialVelocityTracker::get_tracked_linear_velocity() const {
+
+ Vector3 linear_velocity;
+
+ float max_time = 1 / 5.0; //maximum time to interpolate a velocity
+
+ Vector3 distance_accum;
+ float time_accum = 0.0;
+ float base_time = 0.0;
+
+ if (position_history_len) {
+ if (fixed_step) {
+ uint64_t base = Engine::get_singleton()->get_fixed_frames();
+ base_time = float(base - position_history[0].frame) / Engine::get_singleton()->get_iterations_per_second();
+ } else {
+ uint64_t base = Engine::get_singleton()->get_idle_frame_ticks();
+ base_time = double(base - position_history[0].frame) / 1000000.0;
+ }
+ }
+
+ for (int i = 0; i < position_history_len - 1; i++) {
+ float delta = 0.0;
+ uint64_t diff = position_history[i].frame - position_history[i + 1].frame;
+ Vector3 distance = position_history[i].position - position_history[i + 1].position;
+
+ if (fixed_step) {
+ delta = float(diff) / Engine::get_singleton()->get_iterations_per_second();
+ } else {
+ delta = double(diff) / 1000000.0;
+ }
+
+ if (base_time + time_accum + delta > max_time)
+ break;
+
+ distance_accum += distance;
+ time_accum += delta;
+ }
+
+ if (time_accum) {
+ linear_velocity = distance_accum / time_accum;
+ }
+
+ return linear_velocity;
+}
+
+void SpatialVelocityTracker::reset(const Vector3 &p_new_pos) {
+
+ PositionHistory ph;
+ ph.position = p_new_pos;
+ if (fixed_step) {
+ ph.frame = Engine::get_singleton()->get_fixed_frames();
+ } else {
+ ph.frame = Engine::get_singleton()->get_idle_frame_ticks();
+ }
+
+ position_history[0] = ph;
+ position_history_len = 1;
+}
+
+void SpatialVelocityTracker::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_track_fixed_step", "enable"), &SpatialVelocityTracker::set_track_fixed_step);
+ ClassDB::bind_method(D_METHOD("is_tracking_fixed_step"), &SpatialVelocityTracker::is_tracking_fixed_step);
+ ClassDB::bind_method(D_METHOD("update_position", "position"), &SpatialVelocityTracker::update_position);
+ ClassDB::bind_method(D_METHOD("get_tracked_linear_velocity"), &SpatialVelocityTracker::get_tracked_linear_velocity);
+ ClassDB::bind_method(D_METHOD("reset", "position"), &SpatialVelocityTracker::reset);
+}
+
+SpatialVelocityTracker::SpatialVelocityTracker() {
+ position_history.resize(4); // should be configurable
+ position_history_len = 0;
+ fixed_step = false;
+}
diff --git a/scene/3d/spatial_velocity_tracker.h b/scene/3d/spatial_velocity_tracker.h
new file mode 100644
index 0000000000..65f3eaca93
--- /dev/null
+++ b/scene/3d/spatial_velocity_tracker.h
@@ -0,0 +1,31 @@
+#ifndef SPATIAL_VELOCITY_TRACKER_H
+#define SPATIAL_VELOCITY_TRACKER_H
+
+#include "scene/3d/spatial.h"
+
+class SpatialVelocityTracker : public Reference {
+ GDCLASS(SpatialVelocityTracker, Reference)
+
+ struct PositionHistory {
+ uint64_t frame;
+ Vector3 position;
+ };
+
+ bool fixed_step;
+ Vector<PositionHistory> position_history;
+ int position_history_len;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void reset(const Vector3 &p_new_pos);
+ void set_track_fixed_step(bool p_use_fixed_step);
+ bool is_tracking_fixed_step() const;
+ void update_position(const Vector3 &p_position);
+ Vector3 get_tracked_linear_velocity() const;
+
+ SpatialVelocityTracker();
+};
+
+#endif // SPATIAL_VELOCITY_TRACKER_H
diff --git a/scene/audio/audio_player.cpp b/scene/audio/audio_player.cpp
index bcca834642..fdf61c40d8 100644
--- a/scene/audio/audio_player.cpp
+++ b/scene/audio/audio_player.cpp
@@ -263,7 +263,7 @@ void AudioStreamPlayer::_bus_layout_changed() {
void AudioStreamPlayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_stream", "stream:AudioStream"), &AudioStreamPlayer::set_stream);
- ClassDB::bind_method(D_METHOD("get_stream"), &AudioStreamPlayer::get_stream);
+ ClassDB::bind_method(D_METHOD("get_stream:AudioStream"), &AudioStreamPlayer::get_stream);
ClassDB::bind_method(D_METHOD("set_volume_db", "volume_db"), &AudioStreamPlayer::set_volume_db);
ClassDB::bind_method(D_METHOD("get_volume_db"), &AudioStreamPlayer::get_volume_db);
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index c1dbc82f3c..9a5f55698e 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -493,11 +493,11 @@ void BaseButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_enabled_focus_mode", "mode"), &BaseButton::set_enabled_focus_mode);
ClassDB::bind_method(D_METHOD("get_enabled_focus_mode"), &BaseButton::get_enabled_focus_mode);
- ClassDB::bind_method(D_METHOD("set_shortcut", "shortcut"), &BaseButton::set_shortcut);
- ClassDB::bind_method(D_METHOD("get_shortcut"), &BaseButton::get_shortcut);
+ ClassDB::bind_method(D_METHOD("set_shortcut", "shortcut:ShortCut"), &BaseButton::set_shortcut);
+ ClassDB::bind_method(D_METHOD("get_shortcut:ShortCut"), &BaseButton::get_shortcut);
- ClassDB::bind_method(D_METHOD("set_button_group", "button_group"), &BaseButton::set_button_group);
- ClassDB::bind_method(D_METHOD("get_button_group"), &BaseButton::get_button_group);
+ ClassDB::bind_method(D_METHOD("set_button_group", "button_group:ButtonGroup"), &BaseButton::set_button_group);
+ ClassDB::bind_method(D_METHOD("get_button_group:ButtonGroup"), &BaseButton::get_button_group);
BIND_VMETHOD(MethodInfo("_pressed"));
BIND_VMETHOD(MethodInfo("_toggled", PropertyInfo(Variant::BOOL, "pressed")));
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index a456759281..03798c01a2 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -89,7 +89,8 @@ void Button::_notification(int p_what) {
case DRAW_PRESSED: {
style = get_stylebox("pressed");
- style->draw(ci, Rect2(Point2(0, 0), size));
+ if (!flat)
+ style->draw(ci, Rect2(Point2(0, 0), size));
if (has_color("font_color_pressed"))
color = get_color("font_color_pressed");
else
@@ -101,7 +102,8 @@ void Button::_notification(int p_what) {
case DRAW_HOVER: {
style = get_stylebox("hover");
- style->draw(ci, Rect2(Point2(0, 0), size));
+ if (!flat)
+ style->draw(ci, Rect2(Point2(0, 0), size));
color = get_color("font_color_hover");
if (has_color("icon_color_hover"))
color_icon = get_color("icon_color_hover");
@@ -110,7 +112,8 @@ void Button::_notification(int p_what) {
case DRAW_DISABLED: {
style = get_stylebox("disabled");
- style->draw(ci, Rect2(Point2(0, 0), size));
+ if (!flat)
+ style->draw(ci, Rect2(Point2(0, 0), size));
color = get_color("font_color_disabled");
if (has_color("icon_color_disabled"))
color_icon = get_color("icon_color_disabled");
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 9ef340edbc..48cac69956 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -50,6 +50,19 @@ void ColorPicker::_notification(int p_what) {
_update_color();
} break;
+ case NOTIFICATION_PARENTED: {
+ for (int i = 0; i < 4; i++)
+ set_margin((Margin)i, get_constant("margin"));
+ } break;
+
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+ if (get_parent()) {
+ Popup *p = get_parent()->cast_to<Popup>();
+ if (p)
+ p->set_size(Size2(get_combined_minimum_size().width + get_constant("margin") * 2, get_combined_minimum_size().height + get_constant("margin") * 2));
+ }
+ } break;
+
case MainLoop::NOTIFICATION_WM_QUIT_REQUEST: {
if (screen != NULL) {
if (screen->is_visible()) {
@@ -254,13 +267,13 @@ void ColorPicker::_update_text_value() {
}
void ColorPicker::_sample_draw() {
- sample->draw_rect(Rect2(Point2(), Size2(uv_edit->get_size().width, 20)), color);
+ sample->draw_rect(Rect2(Point2(), Size2(uv_edit->get_size().width, sample->get_size().height * 0.95)), color);
}
-void ColorPicker::_hsv_draw(int p_wich, Control *c) {
+void ColorPicker::_hsv_draw(int p_which, Control *c) {
if (!c)
return;
- if (p_wich == 0) {
+ if (p_which == 0) {
Vector<Point2> points;
points.push_back(Vector2());
points.push_back(Vector2(c->get_size().x, 0));
@@ -291,7 +304,7 @@ void ColorPicker::_hsv_draw(int p_wich, Control *c) {
c->draw_line(Point2(x, 0), Point2(x, c->get_size().y), col.inverted());
c->draw_line(Point2(0, y), Point2(c->get_size().x, y), col.inverted());
c->draw_line(Point2(x, y), Point2(x, y), Color(1, 1, 1), 2);
- } else if (p_wich == 1) {
+ } else if (p_which == 1) {
Ref<Texture> hue = get_icon("color_hue", "ColorPicker");
c->draw_texture_rect(hue, Rect2(Point2(), c->get_size()));
int y = c->get_size().y - c->get_size().y * (1.0 - h);
@@ -465,7 +478,7 @@ void ColorPicker::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_raw_mode"), &ColorPicker::is_raw_mode);
ClassDB::bind_method(D_METHOD("set_edit_alpha", "show"), &ColorPicker::set_edit_alpha);
ClassDB::bind_method(D_METHOD("is_editing_alpha"), &ColorPicker::is_editing_alpha);
- ClassDB::bind_method(D_METHOD("add_preset"), &ColorPicker::add_preset);
+ ClassDB::bind_method(D_METHOD("add_preset", "color"), &ColorPicker::add_preset);
ClassDB::bind_method(D_METHOD("_value_changed"), &ColorPicker::_value_changed);
ClassDB::bind_method(D_METHOD("_html_entered"), &ColorPicker::_html_entered);
ClassDB::bind_method(D_METHOD("_text_type_toggled"), &ColorPicker::_text_type_toggled);
@@ -512,23 +525,18 @@ ColorPicker::ColorPicker()
uv_edit->set_mouse_filter(MOUSE_FILTER_PASS);
uv_edit->set_h_size_flags(SIZE_EXPAND_FILL);
uv_edit->set_v_size_flags(SIZE_EXPAND_FILL);
- Vector<Variant> args = Vector<Variant>();
- args.push_back(0);
- args.push_back(uv_edit);
- uv_edit->connect("draw", this, "_hsv_draw", args);
+ uv_edit->set_custom_minimum_size(Size2(get_constant("sv_width"), get_constant("sv_height")));
+ uv_edit->connect("draw", this, "_hsv_draw", make_binds(0, uv_edit));
add_child(hb_edit);
w_edit = memnew(Control);
//w_edit->set_ignore_mouse(false);
- w_edit->set_custom_minimum_size(Size2(30, 0));
+ w_edit->set_custom_minimum_size(Size2(get_constant("h_width"), 0));
w_edit->set_h_size_flags(SIZE_FILL);
w_edit->set_v_size_flags(SIZE_EXPAND_FILL);
w_edit->connect("gui_input", this, "_w_input");
- args.clear();
- args.push_back(1);
- args.push_back(w_edit);
- w_edit->connect("draw", this, "_hsv_draw", args);
+ w_edit->connect("draw", this, "_hsv_draw", make_binds(1, w_edit));
hb_edit->add_child(uv_edit);
hb_edit->add_child(memnew(VSeparator));
@@ -549,10 +557,12 @@ ColorPicker::ColorPicker()
HBoxContainer *hbc = memnew(HBoxContainer);
labels[i] = memnew(Label(lt[i]));
- labels[i]->set_custom_minimum_size(Size2(10, 0));
+ labels[i]->set_custom_minimum_size(Size2(get_constant("label_width"), 0));
+ labels[i]->set_v_size_flags(SIZE_SHRINK_CENTER);
hbc->add_child(labels[i]);
scroll[i] = memnew(HSlider);
+ scroll[i]->set_v_size_flags(SIZE_SHRINK_CENTER);
hbc->add_child(scroll[i]);
values[i] = memnew(SpinBox);
@@ -571,7 +581,7 @@ ColorPicker::ColorPicker()
HBoxContainer *hhb = memnew(HBoxContainer);
btn_mode = memnew(CheckButton);
- btn_mode->set_text(TTR("RAW Mode"));
+ btn_mode->set_text(TTR("Raw Mode"));
btn_mode->connect("toggled", this, "set_raw_mode");
hhb->add_child(btn_mode);
vbr->add_child(hhb);
@@ -617,9 +627,7 @@ void ColorPickerButton::_color_changed(const Color &p_color) {
void ColorPickerButton::pressed() {
- Size2 ms = Size2(300, picker->get_combined_minimum_size().height + 10);
- popup->set_position(get_global_position() - Size2(0, ms.height));
- popup->set_size(ms);
+ popup->set_position(get_global_position() - picker->get_combined_minimum_size());
popup->popup();
picker->set_focus_on_line_edit();
}
diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h
index de624fd029..1a79266409 100644
--- a/scene/gui/color_picker.h
+++ b/scene/gui/color_picker.h
@@ -79,7 +79,7 @@ private:
void _update_text_value();
void _text_type_toggled();
void _sample_draw();
- void _hsv_draw(int p_wich, Control *c);
+ void _hsv_draw(int p_which, Control *c);
void _uv_input(const Ref<InputEvent> &p_input);
void _w_input(const Ref<InputEvent> &p_input);
diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp
index 92bb5d43a7..2a96f8260c 100644
--- a/scene/gui/container.cpp
+++ b/scene/gui/container.cpp
@@ -95,13 +95,25 @@ void Container::fit_child_in_rect(Control *p_child, const Rect2 &p_rect) {
Rect2 r = p_rect;
if (!(p_child->get_h_size_flags() & SIZE_FILL)) {
- r.size.x = minsize.x;
- r.position.x += Math::floor((p_rect.size.x - minsize.x) / 2);
+ r.size.x = minsize.width;
+ if (p_child->get_h_size_flags() & SIZE_SHRINK_END) {
+ r.position.x += p_rect.size.width - minsize.width;
+ } else if (p_child->get_h_size_flags() & SIZE_SHRINK_CENTER) {
+ r.position.x += Math::floor((p_rect.size.x - minsize.width) / 2);
+ } else {
+ r.position.x += 0;
+ }
}
if (!(p_child->get_v_size_flags() & SIZE_FILL)) {
r.size.y = minsize.y;
- r.position.y += Math::floor((p_rect.size.y - minsize.y) / 2);
+ if (p_child->get_v_size_flags() & SIZE_SHRINK_END) {
+ r.position.y += p_rect.size.height - minsize.height;
+ } else if (p_child->get_v_size_flags() & SIZE_SHRINK_CENTER) {
+ r.position.y += Math::floor((p_rect.size.y - minsize.height) / 2);
+ } else {
+ r.position.y += 0;
+ }
}
for (int i = 0; i < 4; i++)
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 45485b768e..ca81b72e89 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "control.h"
-#include "global_config.h"
+#include "project_settings.h"
#include "scene/main/canvas_layer.h"
#include "scene/main/viewport.h"
#include "servers/visual_server.h"
@@ -90,11 +90,22 @@ Size2 Control::edit_get_minimum_size() const {
return get_combined_minimum_size();
}
+Transform2D Control::_get_internal_transform() const {
+
+ Transform2D rot_scale;
+ rot_scale.set_rotation_and_scale(data.rotation, data.scale);
+ Transform2D offset;
+ offset.set_origin(-data.pivot_offset);
+
+ return offset.affine_inverse() * (rot_scale * offset);
+}
void Control::edit_set_rect(const Rect2 &p_edit_rect) {
- Transform2D postxf;
- postxf.set_rotation_and_scale(data.rotation, data.scale);
- Vector2 new_pos = postxf.xform(p_edit_rect.position);
+ Transform2D xform = _get_internal_transform();
+
+ // xform[2] += get_position();
+
+ Vector2 new_pos = xform.basis_xform(p_edit_rect.position);
Vector2 pos = get_position() + new_pos;
@@ -353,8 +364,9 @@ void Control::remove_child_notify(Node *p_child) {
void Control::_update_canvas_item_transform() {
- Transform2D xform = Transform2D(data.rotation, get_position());
- xform.scale_basis(data.scale);
+ Transform2D xform = _get_internal_transform();
+ xform[2] += get_position();
+
VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), xform);
}
@@ -1217,12 +1229,28 @@ void Control::_size_changed() {
}
}
- Point2 new_pos_cache = Point2(margin_pos[0], margin_pos[1]).floor();
- Size2 new_size_cache = Point2(margin_pos[2], margin_pos[3]).floor() - new_pos_cache;
+ Point2 new_pos_cache = Point2(margin_pos[0], margin_pos[1]);
+ Size2 new_size_cache = Point2(margin_pos[2], margin_pos[3]) - new_pos_cache;
+
Size2 minimum_size = get_combined_minimum_size();
- new_size_cache.x = MAX(minimum_size.x, new_size_cache.x);
- new_size_cache.y = MAX(minimum_size.y, new_size_cache.y);
+ if (data.h_grow == GROW_DIRECTION_BEGIN) {
+ if (minimum_size.width > new_size_cache.width) {
+ new_pos_cache.x = new_pos_cache.x + new_size_cache.width - minimum_size.width;
+ new_size_cache.width = minimum_size.width;
+ }
+ } else {
+ new_size_cache.width = MAX(minimum_size.width, new_size_cache.width);
+ }
+
+ if (data.v_grow == GROW_DIRECTION_BEGIN) {
+ if (minimum_size.height > new_size_cache.height) {
+ new_pos_cache.y = new_pos_cache.y + new_size_cache.height - minimum_size.height;
+ new_size_cache.height = minimum_size.height;
+ }
+ } else {
+ new_size_cache.height = MAX(minimum_size.height, new_size_cache.height);
+ }
bool pos_changed = new_pos_cache != data.pos_cache;
bool size_changed = new_size_cache != data.size_cache;
@@ -1887,8 +1915,8 @@ Control::CursorShape Control::get_cursor_shape(const Point2 &p_pos) const {
Transform2D Control::get_transform() const {
- Transform2D xform = Transform2D(data.rotation, get_position());
- xform.scale_basis(data.scale);
+ Transform2D xform = _get_internal_transform();
+ xform[2] += get_position();
return xform;
}
@@ -2214,6 +2242,19 @@ void Control::_font_changed() {
minimum_size_changed(); //fonts affect minimum size pretty much almost always
}
+void Control::set_pivot_offset(const Vector2 &p_pivot) {
+
+ data.pivot_offset = p_pivot;
+ update();
+ _notify_transform();
+ _change_notify("rect_pivot_offset");
+}
+
+Vector2 Control::get_pivot_offset() const {
+
+ return data.pivot_offset;
+}
+
void Control::set_scale(const Vector2 &p_scale) {
data.scale = p_scale;
@@ -2300,6 +2341,27 @@ bool Control::is_clipping_contents() {
return data.clip_contents;
}
+void Control::set_h_grow_direction(GrowDirection p_direction) {
+
+ data.h_grow = p_direction;
+ _size_changed();
+}
+
+Control::GrowDirection Control::get_h_grow_direction() const {
+
+ return data.h_grow;
+}
+
+void Control::set_v_grow_direction(GrowDirection p_direction) {
+
+ data.v_grow = p_direction;
+ _size_changed();
+}
+Control::GrowDirection Control::get_v_grow_direction() const {
+
+ return data.v_grow;
+}
+
void Control::_bind_methods() {
//ClassDB::bind_method(D_METHOD("_window_resize_event"),&Control::_window_resize_event);
@@ -2325,6 +2387,7 @@ void Control::_bind_methods() {
// TODO: Obsolete this method (old name) properly (GH-4397)
ClassDB::bind_method(D_METHOD("_set_rotation_deg", "degrees"), &Control::_set_rotation_deg);
ClassDB::bind_method(D_METHOD("set_scale", "scale"), &Control::set_scale);
+ ClassDB::bind_method(D_METHOD("set_pivot_offset", "pivot_offset"), &Control::set_pivot_offset);
ClassDB::bind_method(D_METHOD("get_margin", "margin"), &Control::get_margin);
ClassDB::bind_method(D_METHOD("get_begin"), &Control::get_begin);
ClassDB::bind_method(D_METHOD("get_end"), &Control::get_end);
@@ -2335,6 +2398,7 @@ void Control::_bind_methods() {
// TODO: Obsolete this method (old name) properly (GH-4397)
ClassDB::bind_method(D_METHOD("_get_rotation_deg"), &Control::_get_rotation_deg);
ClassDB::bind_method(D_METHOD("get_scale"), &Control::get_scale);
+ ClassDB::bind_method(D_METHOD("get_pivot_offset"), &Control::get_pivot_offset);
ClassDB::bind_method(D_METHOD("get_custom_minimum_size"), &Control::get_custom_minimum_size);
ClassDB::bind_method(D_METHOD("get_parent_area_size"), &Control::get_size);
ClassDB::bind_method(D_METHOD("get_global_position"), &Control::get_global_position);
@@ -2388,6 +2452,12 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_parent_control:Control"), &Control::get_parent_control);
+ ClassDB::bind_method(D_METHOD("set_h_grow_direction", "direction"), &Control::set_h_grow_direction);
+ ClassDB::bind_method(D_METHOD("get_h_grow_direction"), &Control::get_h_grow_direction);
+
+ ClassDB::bind_method(D_METHOD("set_v_grow_direction", "direction"), &Control::set_v_grow_direction);
+ ClassDB::bind_method(D_METHOD("get_v_grow_direction"), &Control::get_v_grow_direction);
+
ClassDB::bind_method(D_METHOD("set_tooltip", "tooltip"), &Control::set_tooltip);
ClassDB::bind_method(D_METHOD("get_tooltip", "atpos"), &Control::get_tooltip, DEFVAL(Point2()));
ClassDB::bind_method(D_METHOD("_get_tooltip"), &Control::_get_tooltip);
@@ -2399,7 +2469,7 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_focus_neighbour", "margin", "neighbour"), &Control::set_focus_neighbour);
ClassDB::bind_method(D_METHOD("get_focus_neighbour", "margin"), &Control::get_focus_neighbour);
- ClassDB::bind_method(D_METHOD("force_drag", "data", "preview"), &Control::force_drag);
+ ClassDB::bind_method(D_METHOD("force_drag", "data", "preview:Control"), &Control::force_drag);
ClassDB::bind_method(D_METHOD("set_mouse_filter", "filter"), &Control::set_mouse_filter);
ClassDB::bind_method(D_METHOD("get_mouse_filter"), &Control::get_mouse_filter);
@@ -2438,12 +2508,17 @@ void Control::_bind_methods() {
ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "margin_right", PROPERTY_HINT_RANGE, "-4096,4096"), "set_margin", "get_margin", MARGIN_RIGHT);
ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "margin_bottom", PROPERTY_HINT_RANGE, "-4096,4096"), "set_margin", "get_margin", MARGIN_BOTTOM);
+ ADD_GROUP("Grow Direction", "grow_");
+ ADD_PROPERTYNO(PropertyInfo(Variant::INT, "grow_horizontal", PROPERTY_HINT_ENUM, "Begin,End"), "set_h_grow_direction", "get_h_grow_direction");
+ ADD_PROPERTYNO(PropertyInfo(Variant::INT, "grow_vertical", PROPERTY_HINT_ENUM, "Begin,End"), "set_v_grow_direction", "get_v_grow_direction");
+
ADD_GROUP("Rect", "rect_");
ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "rect_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_position", "get_position");
ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "rect_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_size", "get_size");
ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "rect_min_size"), "set_custom_minimum_size", "get_custom_minimum_size");
ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "rect_rotation", PROPERTY_HINT_RANGE, "-1080,1080,0.01"), "set_rotation_deg", "get_rotation_deg");
ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2, "rect_scale"), "set_scale", "get_scale");
+ ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2, "rect_pivot_offset"), "set_pivot_offset", "get_pivot_offset");
ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "rect_clip_content"), "set_clip_contents", "is_clipping_contents");
ADD_GROUP("Hint", "hint_");
@@ -2459,9 +2534,9 @@ void Control::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_filter", PROPERTY_HINT_ENUM, "Stop,Pass,Ignore"), "set_mouse_filter", "get_mouse_filter");
ADD_GROUP("Size Flags", "size_flags_");
- ADD_PROPERTYNO(PropertyInfo(Variant::INT, "size_flags_horizontal", PROPERTY_HINT_FLAGS, "Fill,Expand"), "set_h_size_flags", "get_h_size_flags");
- ADD_PROPERTYNO(PropertyInfo(Variant::INT, "size_flags_vertical", PROPERTY_HINT_FLAGS, "Fill,Expand"), "set_v_size_flags", "get_v_size_flags");
- ADD_PROPERTYNO(PropertyInfo(Variant::INT, "size_flags_stretch_ratio", PROPERTY_HINT_RANGE, "1,128,0.01"), "set_stretch_ratio", "get_stretch_ratio");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "size_flags_horizontal", PROPERTY_HINT_FLAGS, "Fill,Expand,Shrink Center,Shrink End"), "set_h_size_flags", "get_h_size_flags");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "size_flags_vertical", PROPERTY_HINT_FLAGS, "Fill,Expand,Shrink Center,Shrink End"), "set_v_size_flags", "get_v_size_flags");
+ ADD_PROPERTYNO(PropertyInfo(Variant::REAL, "size_flags_stretch_ratio", PROPERTY_HINT_RANGE, "0,128,0.01"), "set_stretch_ratio", "get_stretch_ratio");
ADD_GROUP("Theme", "");
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), "set_theme", "get_theme");
ADD_GROUP("", "");
@@ -2502,11 +2577,16 @@ void Control::_bind_methods() {
BIND_CONSTANT(SIZE_EXPAND);
BIND_CONSTANT(SIZE_FILL);
BIND_CONSTANT(SIZE_EXPAND_FILL);
+ BIND_CONSTANT(SIZE_SHRINK_CENTER);
+ BIND_CONSTANT(SIZE_SHRINK_END);
BIND_CONSTANT(MOUSE_FILTER_STOP);
BIND_CONSTANT(MOUSE_FILTER_PASS);
BIND_CONSTANT(MOUSE_FILTER_IGNORE);
+ BIND_CONSTANT(GROW_DIRECTION_BEGIN);
+ BIND_CONSTANT(GROW_DIRECTION_END);
+
ADD_SIGNAL(MethodInfo("resized"));
ADD_SIGNAL(MethodInfo("gui_input", PropertyInfo(Variant::OBJECT, "ev", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
ADD_SIGNAL(MethodInfo("mouse_entered"));
@@ -2543,6 +2623,8 @@ Control::Control() {
data.modal_frame = 0;
data.block_minimum_size_adjust = false;
data.disable_visibility_clip = false;
+ data.h_grow = GROW_DIRECTION_END;
+ data.v_grow = GROW_DIRECTION_END;
data.clip_contents = false;
for (int i = 0; i < 4; i++) {
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 5834d1550a..86cf8f6dbd 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -57,6 +57,11 @@ public:
ANCHOR_CENTER,
};
+ enum GrowDirection {
+ GROW_DIRECTION_BEGIN,
+ GROW_DIRECTION_END
+ };
+
enum FocusMode {
FOCUS_NONE,
FOCUS_CLICK,
@@ -67,7 +72,9 @@ public:
SIZE_FILL = 1,
SIZE_EXPAND = 2,
- SIZE_EXPAND_FILL = SIZE_EXPAND | SIZE_FILL
+ SIZE_EXPAND_FILL = SIZE_EXPAND | SIZE_FILL,
+ SIZE_SHRINK_CENTER = 4, //ignored by expand or fill
+ SIZE_SHRINK_END = 8, //ignored by expand or fil
};
@@ -117,9 +124,12 @@ private:
float margin[4];
AnchorType anchor[4];
FocusMode focus_mode;
+ GrowDirection h_grow;
+ GrowDirection v_grow;
float rotation;
Vector2 scale;
+ Vector2 pivot_offset;
bool pending_resize;
@@ -200,6 +210,8 @@ private:
void _update_canvas_item_transform();
+ Transform2D _get_internal_transform() const;
+
friend class Viewport;
void _modal_stack_remove();
void _modal_set_prev_focus_owner(ObjectID p_prev);
@@ -273,6 +285,12 @@ public:
void set_begin(const Point2 &p_point); // helper
void set_end(const Point2 &p_point); // helper
+ void set_h_grow_direction(GrowDirection p_direction);
+ GrowDirection get_h_grow_direction() const;
+
+ void set_v_grow_direction(GrowDirection p_direction);
+ GrowDirection get_v_grow_direction() const;
+
float get_margin(Margin p_margin) const;
Point2 get_begin() const;
Point2 get_end() const;
@@ -293,6 +311,9 @@ public:
float get_rotation() const;
float get_rotation_deg() const;
+ void set_pivot_offset(const Vector2 &p_pivot);
+ Vector2 get_pivot_offset() const;
+
void set_scale(const Vector2 &p_scale);
Vector2 get_scale() const;
@@ -409,5 +430,6 @@ VARIANT_ENUM_CAST(Control::FocusMode);
VARIANT_ENUM_CAST(Control::SizeFlags);
VARIANT_ENUM_CAST(Control::CursorShape);
VARIANT_ENUM_CAST(Control::MouseFilter);
+VARIANT_ENUM_CAST(Control::GrowDirection);
#endif
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index 60d1350405..7d7c636bc2 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -357,6 +357,9 @@ void AcceptDialog::_notification(int p_what) {
if (p_what == NOTIFICATION_MODAL_CLOSE) {
cancel_pressed();
+ } else if (p_what == NOTIFICATION_READY) {
+
+ _update_child_rects();
} else if (p_what == NOTIFICATION_RESIZED) {
_update_child_rects();
@@ -581,5 +584,8 @@ Button *ConfirmationDialog::get_cancel() {
ConfirmationDialog::ConfirmationDialog() {
set_title(RTR("Please Confirm..."));
+#ifdef TOOLS_ENABLED
+ set_custom_minimum_size(Size2(200, 70) * EDSCALE);
+#endif
cancel = add_cancel();
}
diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp
index 58bce57580..22de28ea7f 100644
--- a/scene/gui/gradient_edit.cpp
+++ b/scene/gui/gradient_edit.cpp
@@ -61,10 +61,8 @@ int GradientEdit::_get_point_from_pos(int x) {
void GradientEdit::_show_color_picker() {
if (grabbed == -1)
return;
- Size2 ms = Size2(350, picker->get_combined_minimum_size().height + 10);
picker->set_pick_color(points[grabbed].color);
- popup->set_position(get_global_position() - Vector2(ms.width - get_size().width, ms.height));
- popup->set_size(ms);
+ popup->set_position(get_global_position() - popup->get_combined_minimum_size());
popup->popup();
}
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 8d085d5399..11f750ea70 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -568,7 +568,7 @@ static _FORCE_INLINE_ Vector2 _bezier_interp(real_t t, Vector2 start, Vector2 co
return start * omt3 + control_1 * omt2 * t * 3.0 + control_2 * omt * t2 * 3.0 + end * t3;
}
-void GraphEdit::_bake_segment2d(CanvasItem *p_where, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color &p_color, const Color &p_to_color, int &lines) const {
+void GraphEdit::_bake_segment2d(Vector<Vector2> &points, Vector<Color> &colors, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color &p_color, const Color &p_to_color, int &lines) const {
float mp = p_begin + (p_end - p_begin) * 0.5;
Vector2 beg = _bezier_interp(p_begin, p_a, p_a + p_out, p_b + p_in, p_b);
@@ -581,11 +581,12 @@ void GraphEdit::_bake_segment2d(CanvasItem *p_where, float p_begin, float p_end,
if (p_depth >= p_min_depth && (dp < p_tol || p_depth >= p_max_depth)) {
- p_where->draw_line(beg, end, p_color.linear_interpolate(p_to_color, mp), 2, true);
+ points.push_back((beg + end) * 0.5);
+ colors.push_back(p_color.linear_interpolate(p_to_color, mp));
lines++;
} else {
- _bake_segment2d(p_where, p_begin, mp, p_a, p_out, p_b, p_in, p_depth + 1, p_min_depth, p_max_depth, p_tol, p_color, p_to_color, lines);
- _bake_segment2d(p_where, mp, p_end, p_a, p_out, p_b, p_in, p_depth + 1, p_min_depth, p_max_depth, p_tol, p_color, p_to_color, lines);
+ _bake_segment2d(points, colors, p_begin, mp, p_a, p_out, p_b, p_in, p_depth + 1, p_min_depth, p_max_depth, p_tol, p_color, p_to_color, lines);
+ _bake_segment2d(points, colors, mp, p_end, p_a, p_out, p_b, p_in, p_depth + 1, p_min_depth, p_max_depth, p_tol, p_color, p_to_color, lines);
}
}
@@ -600,7 +601,7 @@ void GraphEdit::_draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const
int cp_neg_len = get_constant("bezier_len_neg");
if (diff > 0) {
- cp_offset = MAX(cp_len, diff * 0.5);
+ cp_offset = MIN(cp_len, diff * 0.5);
} else {
cp_offset = MAX(MIN(cp_len - diff, cp_neg_len), -diff * 0.5);
}
@@ -609,7 +610,16 @@ void GraphEdit::_draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const
Vector2 c2 = Vector2(-cp_offset * zoom, 0);
int lines = 0;
- _bake_segment2d(p_where, 0, 1, p_from, c1, p_to, c2, 0, 3, 9, 8, p_color, p_to_color, lines);
+
+ Vector<Point2> points;
+ Vector<Color> colors;
+ points.push_back(p_from);
+ colors.push_back(p_color);
+ _bake_segment2d(points, colors, 0, 1, p_from, c1, p_to, c2, 0, 3, 9, 8, p_color, p_to_color, lines);
+ points.push_back(p_to);
+ colors.push_back(p_to_color);
+
+ p_where->draw_polyline_colors(points, colors, 2, true);
#else
@@ -1183,7 +1193,7 @@ void GraphEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update_scroll_offset"), &GraphEdit::_update_scroll_offset);
ClassDB::bind_method(D_METHOD("_connections_layer_draw"), &GraphEdit::_connections_layer_draw);
- ClassDB::bind_method(D_METHOD("set_selected", "node"), &GraphEdit::set_selected);
+ ClassDB::bind_method(D_METHOD("set_selected", "node:Node"), &GraphEdit::set_selected);
ADD_SIGNAL(MethodInfo("connection_request", PropertyInfo(Variant::STRING, "from"), PropertyInfo(Variant::INT, "from_slot"), PropertyInfo(Variant::STRING, "to"), PropertyInfo(Variant::INT, "to_slot")));
ADD_SIGNAL(MethodInfo("disconnection_request", PropertyInfo(Variant::STRING, "from"), PropertyInfo(Variant::INT, "from_slot"), PropertyInfo(Variant::STRING, "to"), PropertyInfo(Variant::INT, "to_slot")));
diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h
index 22d053d312..e908829d5f 100644
--- a/scene/gui/graph_edit.h
+++ b/scene/gui/graph_edit.h
@@ -110,7 +110,7 @@ private:
bool awaiting_scroll_offset_update;
List<Connection> connections;
- void _bake_segment2d(CanvasItem *p_where, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color &p_color, const Color &p_to_color, int &lines) const;
+ void _bake_segment2d(Vector<Vector2> &points, Vector<Color> &colors, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color &p_color, const Color &p_to_color, int &lines) const;
void _draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const Vector2 &p_to, const Color &p_color, const Color &p_to_color);
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index 2f0c7b9aaf..97f49da2be 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "item_list.h"
-#include "global_config.h"
#include "os/os.h"
+#include "project_settings.h"
void ItemList::add_item(const String &p_item, const Ref<Texture> &p_texture, bool p_selectable) {
@@ -534,7 +534,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
uint64_t now = OS::get_singleton()->get_ticks_msec();
uint64_t diff = now - search_time_msec;
- if (diff < int(GlobalConfig::get_singleton()->get("gui/timers/incremental_search_max_interval_msec")) * 2) {
+ if (diff < int(ProjectSettings::get_singleton()->get("gui/timers/incremental_search_max_interval_msec")) * 2) {
for (int i = current - 1; i >= 0; i--) {
@@ -569,7 +569,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
uint64_t now = OS::get_singleton()->get_ticks_msec();
uint64_t diff = now - search_time_msec;
- if (diff < int(GlobalConfig::get_singleton()->get("gui/timers/incremental_search_max_interval_msec")) * 2) {
+ if (diff < int(ProjectSettings::get_singleton()->get("gui/timers/incremental_search_max_interval_msec")) * 2) {
for (int i = current + 1; i < items.size(); i++) {
@@ -743,12 +743,10 @@ void ItemList::_notification(int p_what) {
Size2 size = get_size();
- float page = size.height - bg->get_minimum_size().height;
int width = size.width - bg->get_minimum_size().width;
if (scroll_bar->is_visible()) {
width -= mw + bg->get_margin(MARGIN_RIGHT);
}
- scroll_bar->set_page(page);
draw_style_box(bg, Rect2(Point2(), size));
@@ -883,8 +881,12 @@ void ItemList::_notification(int p_what) {
}
if (all_fit) {
+ float page = 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;
scroll_bar->set_max(max);
+ scroll_bar->set_page(page);
//print_line("max: "+rtos(max)+" page "+rtos(page));
if (max <= page) {
scroll_bar->set_value(0);
@@ -1223,6 +1225,56 @@ Vector<int> ItemList::get_selected_items() {
return selected;
}
+void ItemList::_set_items(const Array &p_items) {
+
+ ERR_FAIL_COND(p_items.size() % 3);
+ clear();
+
+ for (int i = 0; i < p_items.size(); i += 3) {
+
+ String text = p_items[i + 0];
+ Ref<Texture> icon = p_items[i + 1];
+ bool disabled = p_items[i + 2];
+
+ int idx = get_item_count();
+ add_item(text, icon);
+ set_item_disabled(idx, disabled);
+ }
+}
+
+Array ItemList::_get_items() const {
+
+ Array items;
+ for (int i = 0; i < get_item_count(); i++) {
+
+ items.push_back(get_item_text(i));
+ items.push_back(get_item_icon(i));
+ items.push_back(is_item_disabled(i));
+ }
+
+ return items;
+}
+
+Size2 ItemList::get_minimum_size() const {
+
+ if (auto_height) {
+ return Size2(0, auto_height_value);
+ }
+ return Size2();
+}
+
+void ItemList::set_auto_height(bool p_enable) {
+
+ auto_height = p_enable;
+ shape_changed = true;
+ update();
+}
+
+bool ItemList::has_auto_height() const {
+
+ return auto_height;
+}
+
void ItemList::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_item", "text", "icon:Texture", "selectable"), &ItemList::add_item, DEFVAL(Variant()), DEFVAL(true));
@@ -1244,7 +1296,7 @@ void ItemList::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_item_disabled", "idx"), &ItemList::is_item_disabled);
ClassDB::bind_method(D_METHOD("set_item_metadata", "idx", "metadata"), &ItemList::set_item_metadata);
- ClassDB::bind_method(D_METHOD("get_item_metadata", "idx"), &ItemList::get_item_metadata);
+ ClassDB::bind_method(D_METHOD("get_item_metadata:Variant", "idx"), &ItemList::get_item_metadata);
ClassDB::bind_method(D_METHOD("set_item_custom_bg_color", "idx", "custom_bg_color"), &ItemList::set_item_custom_bg_color);
ClassDB::bind_method(D_METHOD("get_item_custom_bg_color", "idx"), &ItemList::get_item_custom_bg_color);
@@ -1293,15 +1345,35 @@ void ItemList::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_allow_rmb_select", "allow"), &ItemList::set_allow_rmb_select);
ClassDB::bind_method(D_METHOD("get_allow_rmb_select"), &ItemList::get_allow_rmb_select);
+ ClassDB::bind_method(D_METHOD("set_auto_height", "enable"), &ItemList::set_auto_height);
+ ClassDB::bind_method(D_METHOD("has_auto_height"), &ItemList::has_auto_height);
+
ClassDB::bind_method(D_METHOD("get_item_at_pos", "pos", "exact"), &ItemList::get_item_at_pos, DEFVAL(false));
ClassDB::bind_method(D_METHOD("ensure_current_is_visible"), &ItemList::ensure_current_is_visible);
- ClassDB::bind_method(D_METHOD("get_v_scroll"), &ItemList::get_v_scroll);
+ ClassDB::bind_method(D_METHOD("get_v_scroll:VScrollBar"), &ItemList::get_v_scroll);
ClassDB::bind_method(D_METHOD("_scroll_changed"), &ItemList::_scroll_changed);
ClassDB::bind_method(D_METHOD("_gui_input"), &ItemList::_gui_input);
+ ClassDB::bind_method(D_METHOD("_set_items"), &ItemList::_set_items);
+ ClassDB::bind_method(D_METHOD("_get_items"), &ItemList::_get_items);
+
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_items", "_get_items");
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "select_mode", PROPERTY_HINT_ENUM, "Single,Multi"), "set_select_mode", "get_select_mode");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "allow_rmb_select"), "set_allow_rmb_select", "get_allow_rmb_select");
+ ADD_PROPERTYNO(PropertyInfo(Variant::INT, "max_text_lines"), "set_max_text_lines", "get_max_text_lines");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "auto_height"), "set_auto_height", "has_auto_height");
+ ADD_GROUP("Columns", "");
+ ADD_PROPERTYNO(PropertyInfo(Variant::INT, "max_columns"), "set_max_columns", "get_max_columns");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "same_column_width"), "set_same_column_width", "is_same_column_width");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "fixed_column_width"), "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_PROPERTYNO(PropertyInfo(Variant::REAL, "icon_scale"), "set_icon_scale", "get_icon_scale");
+
BIND_CONSTANT(ICON_MODE_TOP);
BIND_CONSTANT(ICON_MODE_LEFT);
BIND_CONSTANT(SELECT_SINGLE);
@@ -1326,6 +1398,8 @@ ItemList::ItemList() {
same_column_width = false;
max_text_lines = 1;
max_columns = 1;
+ auto_height = false;
+ auto_height_value = 0.0f;
scroll_bar = memnew(VScrollBar);
add_child(scroll_bar);
diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h
index c7abc2990f..137eff8885 100644
--- a/scene/gui/item_list.h
+++ b/scene/gui/item_list.h
@@ -78,6 +78,9 @@ private:
bool ensure_selected_visible;
bool same_column_width;
+ bool auto_height;
+ float auto_height_value;
+
Vector<Item> items;
Vector<int> separators;
@@ -103,6 +106,9 @@ private:
real_t icon_scale;
+ Array _get_items() const;
+ void _set_items(const Array &p_items);
+
void _scroll_changed(double);
void _gui_input(const Ref<InputEvent> &p_event);
@@ -195,6 +201,11 @@ public:
void set_icon_scale(real_t p_scale);
real_t get_icon_scale() const;
+ void set_auto_height(bool p_enable);
+ bool has_auto_height() const;
+
+ Size2 get_minimum_size() const;
+
VScrollBar *get_v_scroll() { return scroll_bar; }
ItemList();
diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp
index fb85930ceb..874156821e 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -28,15 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "label.h"
-#include "global_config.h"
#include "print_string.h"
+#include "project_settings.h"
#include "translation.h"
void Label::set_autowrap(bool p_autowrap) {
autowrap = p_autowrap;
word_cache_dirty = true;
- minimum_size_changed();
update();
}
bool Label::has_autowrap() const {
@@ -48,7 +47,6 @@ void Label::set_uppercase(bool p_uppercase) {
uppercase = p_uppercase;
word_cache_dirty = true;
- minimum_size_changed();
update();
}
bool Label::is_uppercase() const {
@@ -71,7 +69,6 @@ void Label::_notification(int p_what) {
xl_text = new_text;
regenerate_word_cache();
- minimum_size_changed();
update();
}
@@ -292,7 +289,7 @@ void Label::_notification(int p_what) {
Size2 Label::get_minimum_size() const {
if (autowrap)
- return Size2(1, 1);
+ return Size2(1, clip ? 1 : minsize.height);
else {
// don't want to mutable everything
@@ -487,15 +484,16 @@ void Label::regenerate_word_cache() {
}
}
- if (!autowrap) {
+ if (!autowrap)
minsize.width = width;
- if (max_lines_visible > 0 && line_count > max_lines_visible) {
- minsize.height = (font->get_height() * max_lines_visible) + (line_spacing * (max_lines_visible - 1));
- } else {
- minsize.height = (font->get_height() * line_count) + (line_spacing * (line_count - 1));
- }
+
+ if (max_lines_visible > 0 && line_count > max_lines_visible) {
+ minsize.height = (font->get_height() * max_lines_visible) + (line_spacing * (max_lines_visible - 1));
+ } else {
+ minsize.height = (font->get_height() * line_count) + (line_spacing * (line_count - 1));
}
+ minimum_size_changed();
word_cache_dirty = false;
}
@@ -533,9 +531,6 @@ void Label::set_text(const String &p_string) {
if (percent_visible < 1)
visible_chars = get_total_character_count() * percent_visible;
update();
- if (!autowrap) {
- minimum_size_changed();
- }
}
void Label::set_clip_text(bool p_clip) {
@@ -686,6 +681,7 @@ Label::Label(const String &p_text) {
max_lines_visible = -1;
set_text(p_text);
uppercase = false;
+ set_v_size_flags(SIZE_SHRINK_CENTER);
}
Label::~Label() {
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index bc579020bd..f4dd3e92cd 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -574,8 +574,12 @@ void LineEdit::_notification(int p_what) {
RID ci = get_canvas_item();
Ref<StyleBox> style = get_stylebox("normal");
- if (!is_editable())
+ float disabled_alpha = 1.0; // used to set the disabled input text color
+ if (!is_editable()) {
style = get_stylebox("read_only");
+ disabled_alpha = .5;
+ draw_caret = false;
+ }
Ref<Font> font = get_font("font");
@@ -622,6 +626,13 @@ void LineEdit::_notification(int p_what) {
// draw placeholder color
if (text.empty())
font_color.a *= placeholder_alpha;
+ font_color.a *= disabled_alpha;
+
+ if (has_icon("right_icon")) {
+ Ref<Texture> r_icon = Control::get_icon("right_icon");
+ ofs_max -= r_icon->get_width();
+ r_icon->draw(ci, Point2(width - r_icon->get_width() - x_ofs, y_ofs), Color(1, 1, 1, disabled_alpha * .9));
+ }
int caret_height = font->get_height() > y_area ? y_area : font->get_height();
while (true) {
@@ -660,6 +671,11 @@ void LineEdit::_notification(int p_what) {
Point2(x_ofs, y_ofs), Size2(1, caret_height)),
cursor_color);
}
+
+ if (has_focus()) {
+
+ OS::get_singleton()->set_ime_position(get_global_position() + Point2(x_ofs, y_ofs + caret_height));
+ }
} break;
case NOTIFICATION_FOCUS_ENTER: {
@@ -667,12 +683,17 @@ void LineEdit::_notification(int p_what) {
draw_caret = true;
}
+ Point2 cursor_pos = Point2(get_cursor_pos(), 1) * get_minimum_size().height;
+ 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());
} break;
case NOTIFICATION_FOCUS_EXIT: {
+ OS::get_singleton()->set_ime_position(Point2());
+
if (OS::get_singleton()->has_virtual_keyboard())
OS::get_singleton()->hide_virtual_keyboard();
@@ -1181,7 +1202,9 @@ void LineEdit::menu_option(int p_option) {
select_all();
} break;
case MENU_UNDO: {
- undo();
+ if (editable) {
+ undo();
+ }
} break;
}
}
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index 0806d35d48..b842419eab 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -52,11 +52,26 @@ void OptionButton::_notification(int p_what) {
RID ci = get_canvas_item();
Ref<Texture> arrow = Control::get_icon("arrow");
Ref<StyleBox> normal = get_stylebox("normal");
+ Color clr = Color(1, 1, 1);
+ if (get_constant("modulate_arrow"))
+ switch (get_draw_mode()) {
+ case DRAW_PRESSED:
+ clr = get_color("font_color_pressed");
+ break;
+ case DRAW_HOVER:
+ clr = get_color("font_color_hover");
+ break;
+ case DRAW_DISABLED:
+ clr = get_color("font_color_disabled");
+ break;
+ default:
+ clr = get_color("font_color");
+ }
Size2 size = get_size();
Point2 ofs(size.width - arrow->get_width() - get_constant("arrow_margin"), int(Math::abs((size.height - arrow->get_height()) / 2)));
- arrow->draw(ci, ofs);
+ arrow->draw(ci, ofs, clr);
} break;
}
@@ -283,7 +298,7 @@ void OptionButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_item_text", "idx"), &OptionButton::get_item_text);
ClassDB::bind_method(D_METHOD("get_item_icon:Texture", "idx"), &OptionButton::get_item_icon);
ClassDB::bind_method(D_METHOD("get_item_ID", "idx"), &OptionButton::get_item_ID);
- ClassDB::bind_method(D_METHOD("get_item_metadata", "idx"), &OptionButton::get_item_metadata);
+ ClassDB::bind_method(D_METHOD("get_item_metadata:Variant", "idx"), &OptionButton::get_item_metadata);
ClassDB::bind_method(D_METHOD("is_item_disabled", "idx"), &OptionButton::is_item_disabled);
ClassDB::bind_method(D_METHOD("get_item_count"), &OptionButton::get_item_count);
ClassDB::bind_method(D_METHOD("add_separator"), &OptionButton::add_separator);
@@ -291,7 +306,7 @@ void OptionButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("select", "idx"), &OptionButton::select);
ClassDB::bind_method(D_METHOD("get_selected"), &OptionButton::get_selected);
ClassDB::bind_method(D_METHOD("get_selected_ID"), &OptionButton::get_selected_ID);
- ClassDB::bind_method(D_METHOD("get_selected_metadata"), &OptionButton::get_selected_metadata);
+ ClassDB::bind_method(D_METHOD("get_selected_metadata:Variant"), &OptionButton::get_selected_metadata);
ClassDB::bind_method(D_METHOD("remove_item", "idx"), &OptionButton::remove_item);
ClassDB::bind_method(D_METHOD("_select_int"), &OptionButton::_select_int);
diff --git a/scene/gui/patch_9_rect.cpp b/scene/gui/patch_9_rect.cpp
index 249090830d..e577000f99 100644
--- a/scene/gui/patch_9_rect.cpp
+++ b/scene/gui/patch_9_rect.cpp
@@ -54,8 +54,8 @@ Size2 NinePatchRect::get_minimum_size() const {
}
void NinePatchRect::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_texture", "texture"), &NinePatchRect::set_texture);
- ClassDB::bind_method(D_METHOD("get_texture"), &NinePatchRect::get_texture);
+ ClassDB::bind_method(D_METHOD("set_texture", "texture:Texture"), &NinePatchRect::set_texture);
+ ClassDB::bind_method(D_METHOD("get_texture:Texture"), &NinePatchRect::get_texture);
ClassDB::bind_method(D_METHOD("set_patch_margin", "margin", "value"), &NinePatchRect::set_patch_margin);
ClassDB::bind_method(D_METHOD("get_patch_margin", "margin"), &NinePatchRect::get_patch_margin);
ClassDB::bind_method(D_METHOD("set_region_rect", "rect"), &NinePatchRect::set_region_rect);
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 74b26da580..f59a2e06eb 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -696,6 +696,17 @@ String PopupMenu::get_item_text(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, items.size(), "");
return items[p_idx].text;
}
+
+int PopupMenu::get_item_idx_from_text(const String &text) const {
+
+ for (int idx = 0; idx < items.size(); idx++) {
+ if (items[idx].text == text)
+ return idx;
+ }
+
+ return -1;
+}
+
Ref<Texture> PopupMenu::get_item_icon(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, items.size(), Ref<Texture>());
@@ -1064,19 +1075,19 @@ void PopupMenu::clear_autohide_areas() {
void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("_gui_input"), &PopupMenu::_gui_input);
- ClassDB::bind_method(D_METHOD("add_icon_item", "texture", "label", "id", "accel"), &PopupMenu::add_icon_item, DEFVAL(-1), DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("add_icon_item", "texture:Texture", "label", "id", "accel"), &PopupMenu::add_icon_item, DEFVAL(-1), DEFVAL(0));
ClassDB::bind_method(D_METHOD("add_item", "label", "id", "accel"), &PopupMenu::add_item, DEFVAL(-1), DEFVAL(0));
- ClassDB::bind_method(D_METHOD("add_icon_check_item", "texture", "label", "id", "accel"), &PopupMenu::add_icon_check_item, DEFVAL(-1), DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("add_icon_check_item", "texture:Texture", "label", "id", "accel"), &PopupMenu::add_icon_check_item, DEFVAL(-1), DEFVAL(0));
ClassDB::bind_method(D_METHOD("add_check_item", "label", "id", "accel"), &PopupMenu::add_check_item, DEFVAL(-1), DEFVAL(0));
ClassDB::bind_method(D_METHOD("add_submenu_item", "label", "submenu", "id"), &PopupMenu::add_submenu_item, DEFVAL(-1));
- ClassDB::bind_method(D_METHOD("add_icon_shortcut", "texture", "shortcut:ShortCut", "id", "global"), &PopupMenu::add_icon_shortcut, DEFVAL(-1), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("add_icon_shortcut", "texture:Texture", "shortcut:ShortCut", "id", "global"), &PopupMenu::add_icon_shortcut, DEFVAL(-1), DEFVAL(false));
ClassDB::bind_method(D_METHOD("add_shortcut", "shortcut:ShortCut", "id", "global"), &PopupMenu::add_shortcut, DEFVAL(-1), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("add_icon_check_shortcut", "texture", "shortcut:ShortCut", "id", "global"), &PopupMenu::add_icon_check_shortcut, DEFVAL(-1), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("add_icon_check_shortcut", "texture:Texture", "shortcut:ShortCut", "id", "global"), &PopupMenu::add_icon_check_shortcut, DEFVAL(-1), DEFVAL(false));
ClassDB::bind_method(D_METHOD("add_check_shortcut", "shortcut:ShortCut", "id", "global"), &PopupMenu::add_check_shortcut, DEFVAL(-1), DEFVAL(false));
ClassDB::bind_method(D_METHOD("set_item_text", "idx", "text"), &PopupMenu::set_item_text);
- ClassDB::bind_method(D_METHOD("set_item_icon", "idx", "icon"), &PopupMenu::set_item_icon);
+ ClassDB::bind_method(D_METHOD("set_item_icon", "idx", "icon:Texture"), &PopupMenu::set_item_icon);
ClassDB::bind_method(D_METHOD("set_item_checked", "idx", "checked"), &PopupMenu::set_item_checked);
ClassDB::bind_method(D_METHOD("set_item_ID", "idx", "id"), &PopupMenu::set_item_ID);
ClassDB::bind_method(D_METHOD("set_item_accelerator", "idx", "accel"), &PopupMenu::set_item_accelerator);
@@ -1091,12 +1102,12 @@ void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("toggle_item_checked", "idx"), &PopupMenu::toggle_item_checked);
ClassDB::bind_method(D_METHOD("get_item_text", "idx"), &PopupMenu::get_item_text);
- ClassDB::bind_method(D_METHOD("get_item_icon", "idx"), &PopupMenu::get_item_icon);
+ ClassDB::bind_method(D_METHOD("get_item_icon:Texture", "idx"), &PopupMenu::get_item_icon);
ClassDB::bind_method(D_METHOD("is_item_checked", "idx"), &PopupMenu::is_item_checked);
ClassDB::bind_method(D_METHOD("get_item_ID", "idx"), &PopupMenu::get_item_ID);
ClassDB::bind_method(D_METHOD("get_item_index", "id"), &PopupMenu::get_item_index);
ClassDB::bind_method(D_METHOD("get_item_accelerator", "idx"), &PopupMenu::get_item_accelerator);
- ClassDB::bind_method(D_METHOD("get_item_metadata", "idx"), &PopupMenu::get_item_metadata);
+ ClassDB::bind_method(D_METHOD("get_item_metadata:Variant", "idx"), &PopupMenu::get_item_metadata);
ClassDB::bind_method(D_METHOD("is_item_disabled", "idx"), &PopupMenu::is_item_disabled);
ClassDB::bind_method(D_METHOD("get_item_submenu", "idx"), &PopupMenu::get_item_submenu);
ClassDB::bind_method(D_METHOD("is_item_separator", "idx"), &PopupMenu::is_item_separator);
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index a9bd8f7e50..6f1a2db363 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -132,6 +132,7 @@ public:
void toggle_item_checked(int p_idx);
String get_item_text(int p_idx) const;
+ int get_item_idx_from_text(const String &text) const;
Ref<Texture> get_item_icon(int p_idx) const;
bool is_item_checked(int p_idx) const;
int get_item_ID(int p_idx) const;
diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp
index 7158592bb1..6bec365dcf 100644
--- a/scene/gui/range.cpp
+++ b/scene/gui/range.cpp
@@ -234,7 +234,7 @@ void Range::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_exp_ratio", "enabled"), &Range::set_exp_ratio);
ClassDB::bind_method(D_METHOD("is_ratio_exp"), &Range::is_ratio_exp);
- ClassDB::bind_method(D_METHOD("share", "with"), &Range::_share);
+ ClassDB::bind_method(D_METHOD("share", "with:Node"), &Range::_share);
ClassDB::bind_method(D_METHOD("unshare"), &Range::unshare);
ADD_SIGNAL(MethodInfo("value_changed", PropertyInfo(Variant::REAL, "value")));
@@ -273,8 +273,8 @@ Range::Range() {
shared = memnew(Shared);
shared->min = 0;
shared->max = 100;
- shared->val =
- shared->step = 1;
+ shared->val = 0;
+ shared->step = 1;
shared->page = 0;
shared->owners.insert(this);
shared->exp_ratio = false;
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 78ede6e494..9f71fa070c 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -1822,15 +1822,40 @@ String RichTextLabel::get_text() {
return text;
}
+void RichTextLabel::set_text(const String &p_string) {
+ clear();
+ add_text(p_string);
+}
+
+void RichTextLabel::set_percent_visible(float p_percent) {
+
+ if (p_percent < 0 || p_percent >= 1) {
+
+ visible_characters = -1;
+ percent_visible = 1;
+
+ } else {
+
+ visible_characters = get_total_character_count() * p_percent;
+ percent_visible = p_percent;
+ }
+ update();
+}
+
+float RichTextLabel::get_percent_visible() const {
+ return percent_visible;
+}
+
void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("_gui_input"), &RichTextLabel::_gui_input);
ClassDB::bind_method(D_METHOD("_scroll_changed"), &RichTextLabel::_scroll_changed);
ClassDB::bind_method(D_METHOD("get_text"), &RichTextLabel::get_text);
ClassDB::bind_method(D_METHOD("add_text", "text"), &RichTextLabel::add_text);
+ ClassDB::bind_method(D_METHOD("set_text", "text"), &RichTextLabel::set_text);
ClassDB::bind_method(D_METHOD("add_image", "image:Texture"), &RichTextLabel::add_image);
ClassDB::bind_method(D_METHOD("newline"), &RichTextLabel::add_newline);
- ClassDB::bind_method(D_METHOD("remove_line"), &RichTextLabel::remove_line);
+ ClassDB::bind_method(D_METHOD("remove_line", "line"), &RichTextLabel::remove_line);
ClassDB::bind_method(D_METHOD("push_font", "font:Font"), &RichTextLabel::push_font);
ClassDB::bind_method(D_METHOD("push_color", "color"), &RichTextLabel::push_color);
ClassDB::bind_method(D_METHOD("push_align", "align"), &RichTextLabel::push_align);
@@ -1873,6 +1898,9 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_visible_characters", "amount"), &RichTextLabel::set_visible_characters);
ClassDB::bind_method(D_METHOD("get_visible_characters"), &RichTextLabel::get_visible_characters);
+ ClassDB::bind_method(D_METHOD("set_percent_visible", "percent_visible"), &RichTextLabel::set_percent_visible);
+ ClassDB::bind_method(D_METHOD("get_percent_visible"), &RichTextLabel::get_percent_visible);
+
ClassDB::bind_method(D_METHOD("get_total_character_count"), &RichTextLabel::get_total_character_count);
ClassDB::bind_method(D_METHOD("set_use_bbcode", "enable"), &RichTextLabel::set_use_bbcode);
@@ -1881,7 +1909,9 @@ void RichTextLabel::_bind_methods() {
ADD_GROUP("BBCode", "bbcode_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bbcode_enabled"), "set_use_bbcode", "is_using_bbcode");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "bbcode_text", PROPERTY_HINT_MULTILINE_TEXT), "set_bbcode", "get_bbcode");
+
ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters", PROPERTY_HINT_RANGE, "-1,128000,1"), "set_visible_characters", "get_visible_characters");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "percent_visible", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_percent_visible", "get_percent_visible");
ADD_SIGNAL(MethodInfo("meta_clicked", PropertyInfo(Variant::NIL, "meta")));
@@ -1914,7 +1944,6 @@ void RichTextLabel::set_visible_characters(int p_visible) {
}
int RichTextLabel::get_visible_characters() const {
-
return visible_characters;
}
int RichTextLabel::get_total_character_count() const {
@@ -1964,11 +1993,11 @@ RichTextLabel::RichTextLabel() {
selection.enabled = false;
visible_characters = -1;
+ percent_visible = 1;
set_clip_contents(true);
}
RichTextLabel::~RichTextLabel() {
-
memdelete(main);
}
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index eedb7e54db..409a8f6b3f 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -258,6 +258,7 @@ private:
Selection selection;
int visible_characters;
+ float percent_visible;
void _process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &y, int p_width, int p_line, ProcessMode p_mode, const Ref<Font> &p_base_font, const Color &p_base_color, const Point2i &p_click_pos = Point2i(), Item **r_click_item = NULL, int *r_click_char = NULL, bool *r_outside = NULL, int p_char_count = 0);
void _find_click(ItemFrame *p_frame, const Point2i &p_click, Item **r_click_item = NULL, int *r_click_char = NULL, bool *r_outside = NULL);
@@ -340,10 +341,15 @@ public:
void set_bbcode(const String &p_bbcode);
String get_bbcode() const;
+ void set_text(const String &p_string);
+
void set_visible_characters(int p_visible);
int get_visible_characters() const;
int get_total_character_count() const;
+ void set_percent_visible(float p_percent);
+ float get_percent_visible() const;
+
RichTextLabel();
~RichTextLabel();
};
diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp
index d0e708bf73..9ba17ce34f 100644
--- a/scene/gui/slider.cpp
+++ b/scene/gui/slider.cpp
@@ -39,6 +39,10 @@ Size2 Slider::get_minimum_size() const {
void Slider::_gui_input(Ref<InputEvent> p_event) {
+ if (!editable) {
+ return;
+ }
+
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
@@ -158,12 +162,13 @@ void Slider::_notification(int p_what) {
Size2i size = get_size();
Ref<StyleBox> style = get_stylebox("slider");
Ref<StyleBox> focus = get_stylebox("focus");
- Ref<Texture> grabber = get_icon(mouse_inside || has_focus() ? "grabber_highlight" : "grabber");
+ Ref<Texture> grabber = get_icon(editable ? ((mouse_inside || has_focus()) ? "grabber_highlight" : "grabber") : "grabber_disabled");
Ref<Texture> tick = get_icon("tick");
if (orientation == VERTICAL) {
- style->draw(ci, Rect2i(Point2i(), Size2i(style->get_minimum_size().width + style->get_center_size().width, size.height)));
+ int widget_width = style->get_minimum_size().width + style->get_center_size().width;
+ style->draw(ci, Rect2i(Point2i(size.width / 2 - widget_width / 2, 0), Size2i(widget_width, size.height)));
/*
if (mouse_inside||has_focus())
focus->draw(ci,Rect2i(Point2i(),Size2i(style->get_minimum_size().width+style->get_center_size().width,size.height)));
@@ -179,7 +184,9 @@ void Slider::_notification(int p_what) {
}
grabber->draw(ci, Point2i(size.width / 2 - grabber->get_size().width / 2, size.height - get_as_ratio() * areasize - grabber->get_size().height));
} else {
- style->draw(ci, Rect2i(Point2i(), Size2i(size.width, style->get_minimum_size().height + style->get_center_size().height)));
+
+ int widget_height = style->get_minimum_size().height + style->get_center_size().height;
+ style->draw(ci, Rect2i(Point2i(0, size.height / 2 - widget_height / 2), Size2i(size.width, 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)));
@@ -231,6 +238,17 @@ void Slider::set_ticks_on_borders(bool _tob) {
update();
}
+void Slider::set_editable(bool p_editable) {
+
+ editable = p_editable;
+ update();
+}
+
+bool Slider::is_editable() const {
+
+ return editable;
+}
+
void Slider::_bind_methods() {
ClassDB::bind_method(D_METHOD("_gui_input"), &Slider::_gui_input);
@@ -240,6 +258,10 @@ void Slider::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_ticks_on_borders"), &Slider::get_ticks_on_borders);
ClassDB::bind_method(D_METHOD("set_ticks_on_borders", "ticks_on_border"), &Slider::set_ticks_on_borders);
+ ClassDB::bind_method(D_METHOD("set_editable", "editable"), &Slider::set_editable);
+ ClassDB::bind_method(D_METHOD("is_editable"), &Slider::is_editable);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editable"), "set_editable", "is_editable");
ADD_PROPERTY(PropertyInfo(Variant::INT, "tick_count", PROPERTY_HINT_RANGE, "0,4096,1"), "set_ticks", "get_ticks");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ticks_on_borders"), "set_ticks_on_borders", "get_ticks_on_borders");
ADD_PROPERTY(PropertyInfo(Variant::INT, "focus_mode", PROPERTY_HINT_ENUM, "None,Click,All"), "set_focus_mode", "get_focus_mode");
@@ -251,5 +273,6 @@ Slider::Slider(Orientation p_orientation) {
grab.active = false;
ticks = 0;
custom_step = -1;
+ editable = true;
set_focus_mode(FOCUS_ALL);
}
diff --git a/scene/gui/slider.h b/scene/gui/slider.h
index 7194484058..f3cf3c6f48 100644
--- a/scene/gui/slider.h
+++ b/scene/gui/slider.h
@@ -46,6 +46,7 @@ class Slider : public Range {
bool mouse_inside;
Orientation orientation;
float custom_step;
+ bool editable;
protected:
void _gui_input(Ref<InputEvent> p_event);
@@ -65,6 +66,9 @@ public:
void set_ticks_on_borders(bool);
bool get_ticks_on_borders() const;
+ void set_editable(bool p_editable);
+ bool is_editable() const;
+
Slider(Orientation p_orientation = VERTICAL);
};
diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index c5b9df15b9..1ba6e6e4bd 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -253,7 +253,7 @@ void SpinBox::_bind_methods() {
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("_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("get_line_edit:LineEdit"), &SpinBox::get_line_edit);
ClassDB::bind_method(D_METHOD("_line_edit_input"), &SpinBox::_line_edit_input);
ClassDB::bind_method(D_METHOD("_range_click_timeout"), &SpinBox::_range_click_timeout);
diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp
index 31236fa277..e3dad08809 100644
--- a/scene/gui/split_container.cpp
+++ b/scene/gui/split_container.cpp
@@ -131,7 +131,12 @@ void SplitContainer::_resort() {
if (ratiomode) {
- middle_sep = ms_first[axis] + available / 2;
+ int first_ratio = first->get_stretch_ratio();
+ int second_ratio = second->get_stretch_ratio();
+
+ float ratio = float(first_ratio) / (first_ratio + second_ratio);
+
+ middle_sep = ms_first[axis] + available * ratio;
} else if (expand_first_mode) {
@@ -144,12 +149,17 @@ void SplitContainer::_resort() {
} else if (ratiomode) {
- if (expand_ofs < -(available / 2))
- expand_ofs = -(available / 2);
- else if (expand_ofs > (available / 2))
- expand_ofs = (available / 2);
+ int first_ratio = first->get_stretch_ratio();
+ int second_ratio = second->get_stretch_ratio();
+
+ float ratio = float(first_ratio) / (first_ratio + second_ratio);
+
+ if (expand_ofs < -(available * ratio))
+ expand_ofs = -(available * ratio);
+ else if (expand_ofs > (available * (1.0 - ratio)))
+ expand_ofs = (available * (1.0 - ratio));
- middle_sep = ms_first[axis] + available / 2 + expand_ofs;
+ middle_sep = ms_first[axis] + available * ratio + expand_ofs;
} else if (expand_first_mode) {
diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp
index 600493b439..24eb19fbc2 100644
--- a/scene/gui/tabs.cpp
+++ b/scene/gui/tabs.cpp
@@ -593,8 +593,44 @@ void Tabs::remove_tab(int p_idx) {
_ensure_no_over_offset();
}
+Variant Tabs::get_drag_data(const Point2 &p_point) {
+
+ return get_tab_idx_at_point(p_point);
+}
+
+bool Tabs::can_drop_data(const Point2 &p_point, const Variant &p_data) const {
+
+ return get_tab_idx_at_point(p_point) > -1;
+}
+
+void Tabs::drop_data(const Point2 &p_point, const Variant &p_data) {
+
+ int hover_now = get_tab_idx_at_point(p_point);
+
+ ERR_FAIL_INDEX(hover_now, tabs.size());
+ emit_signal("reposition_active_tab_request", hover_now);
+}
+
+int Tabs::get_tab_idx_at_point(const Point2 &p_point) const {
+
+ int hover_now = -1;
+ for (int i = 0; i < tabs.size(); i++) {
+
+ if (i < offset)
+ continue;
+
+ Rect2 rect = get_tab_rect(i);
+ if (rect.has_point(p_point)) {
+ hover_now = i;
+ }
+ }
+
+ return hover_now;
+}
+
void Tabs::set_tab_align(TabAlign p_align) {
+ ERR_FAIL_INDEX(p_align, ALIGN_MAX);
tab_align = p_align;
update();
}
@@ -604,6 +640,22 @@ Tabs::TabAlign Tabs::get_tab_align() const {
return tab_align;
}
+void Tabs::move_tab(int from, int to) {
+
+ if (from == to)
+ return;
+
+ ERR_FAIL_INDEX(from, tabs.size());
+ ERR_FAIL_INDEX(to, tabs.size());
+
+ Tab tab_from = tabs[from];
+ tabs.remove(from);
+ tabs.insert(to, tab_from);
+
+ _update_cache();
+ update();
+}
+
int Tabs::get_tab_width(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, tabs.size(), 0);
@@ -708,15 +760,22 @@ void Tabs::ensure_tab_visible(int p_idx) {
}
}
-Rect2 Tabs::get_tab_rect(int p_tab) {
+Rect2 Tabs::get_tab_rect(int p_tab) const {
return Rect2(tabs[p_tab].ofs_cache, 0, tabs[p_tab].size_cache, get_size().height);
}
void Tabs::set_tab_close_display_policy(CloseButtonDisplayPolicy p_policy) {
+
+ ERR_FAIL_INDEX(p_policy, CLOSE_BUTTON_MAX);
cb_displaypolicy = p_policy;
update();
}
+Tabs::CloseButtonDisplayPolicy Tabs::get_tab_close_display_policy() const {
+
+ return cb_displaypolicy;
+}
+
void Tabs::set_min_width(int p_width) {
min_width = p_width;
}
@@ -734,25 +793,33 @@ void Tabs::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_tab_disabled", "tab_idx", "disabled"), &Tabs::set_tab_disabled);
ClassDB::bind_method(D_METHOD("get_tab_disabled", "tab_idx"), &Tabs::get_tab_disabled);
ClassDB::bind_method(D_METHOD("remove_tab", "tab_idx"), &Tabs::remove_tab);
- ClassDB::bind_method(D_METHOD("add_tab", "title", "icon:Texture"), &Tabs::add_tab);
+ ClassDB::bind_method(D_METHOD("add_tab", "title", "icon:Texture"), &Tabs::add_tab, DEFVAL(""), DEFVAL(Ref<Texture>()));
ClassDB::bind_method(D_METHOD("set_tab_align", "align"), &Tabs::set_tab_align);
ClassDB::bind_method(D_METHOD("get_tab_align"), &Tabs::get_tab_align);
ClassDB::bind_method(D_METHOD("ensure_tab_visible", "idx"), &Tabs::ensure_tab_visible);
+ ClassDB::bind_method(D_METHOD("get_tab_rect", "tab_idx"), &Tabs::get_tab_rect);
+ ClassDB::bind_method(D_METHOD("move_tab", "from", "to"), &Tabs::move_tab);
+ ClassDB::bind_method(D_METHOD("set_tab_close_display_policy", "policy"), &Tabs::set_tab_close_display_policy);
+ ClassDB::bind_method(D_METHOD("get_tab_close_display_policy"), &Tabs::get_tab_close_display_policy);
ADD_SIGNAL(MethodInfo("tab_changed", PropertyInfo(Variant::INT, "tab")));
ADD_SIGNAL(MethodInfo("right_button_pressed", PropertyInfo(Variant::INT, "tab")));
ADD_SIGNAL(MethodInfo("tab_close", PropertyInfo(Variant::INT, "tab")));
ADD_SIGNAL(MethodInfo("tab_hover", PropertyInfo(Variant::INT, "tab")));
+ ADD_SIGNAL(MethodInfo("reposition_active_tab_request", PropertyInfo(Variant::INT, "idx_to")));
ADD_PROPERTY(PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE, "-1,4096,1", PROPERTY_USAGE_EDITOR), "set_current_tab", "get_current_tab");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "tab_close_display_policy", PROPERTY_HINT_ENUM, "Show Never,Show Active Only,Show Always"), "set_tab_close_display_policy", "get_tab_close_display_policy");
BIND_CONSTANT(ALIGN_LEFT);
BIND_CONSTANT(ALIGN_CENTER);
BIND_CONSTANT(ALIGN_RIGHT);
+ BIND_CONSTANT(ALIGN_MAX);
BIND_CONSTANT(CLOSE_BUTTON_SHOW_ACTIVE_ONLY);
BIND_CONSTANT(CLOSE_BUTTON_SHOW_ALWAYS);
BIND_CONSTANT(CLOSE_BUTTON_SHOW_NEVER);
+ BIND_CONSTANT(CLOSE_BUTTON_MAX);
}
Tabs::Tabs() {
diff --git a/scene/gui/tabs.h b/scene/gui/tabs.h
index 65d409c410..86ad128dcd 100644
--- a/scene/gui/tabs.h
+++ b/scene/gui/tabs.h
@@ -41,7 +41,8 @@ public:
ALIGN_LEFT,
ALIGN_CENTER,
- ALIGN_RIGHT
+ ALIGN_RIGHT,
+ ALIGN_MAX
};
enum CloseButtonDisplayPolicy {
@@ -49,6 +50,7 @@ public:
CLOSE_BUTTON_SHOW_NEVER,
CLOSE_BUTTON_SHOW_ACTIVE_ONLY,
CLOSE_BUTTON_SHOW_ALWAYS,
+ CLOSE_BUTTON_MAX
};
private:
@@ -96,6 +98,11 @@ protected:
void _notification(int p_what);
static void _bind_methods();
+ Variant get_drag_data(const Point2 &p_point);
+ bool can_drop_data(const Point2 &p_point, const Variant &p_data) const;
+ void drop_data(const Point2 &p_point, const Variant &p_data);
+ int get_tab_idx_at_point(const Point2 &p_point) const;
+
public:
void add_tab(const String &p_str = "", const Ref<Texture> &p_icon = Ref<Texture>());
@@ -114,7 +121,10 @@ public:
void set_tab_align(TabAlign p_align);
TabAlign get_tab_align() const;
+ void move_tab(int from, int to);
+
void set_tab_close_display_policy(CloseButtonDisplayPolicy p_policy);
+ CloseButtonDisplayPolicy get_tab_close_display_policy() const;
int get_tab_count() const;
void set_current_tab(int p_current);
@@ -128,12 +138,13 @@ public:
void ensure_tab_visible(int p_idx);
void set_min_width(int p_width);
- Rect2 get_tab_rect(int p_tab);
+ Rect2 get_tab_rect(int p_tab) const;
Size2 get_minimum_size() const;
Tabs();
};
VARIANT_ENUM_CAST(Tabs::TabAlign);
+VARIANT_ENUM_CAST(Tabs::CloseButtonDisplayPolicy);
#endif // TABS_H
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 936a9b77f8..8baca50d32 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -33,8 +33,8 @@
#include "os/keyboard.h"
#include "os/os.h"
-#include "global_config.h"
#include "message_queue.h"
+#include "project_settings.h"
#include "scene/main/viewport.h"
#define TAB_PIXELS
@@ -1191,12 +1191,19 @@ void TextEdit::_notification(int p_what) {
}
}
+ if (has_focus()) {
+ OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos + Point2(0, get_row_height()));
+ }
} break;
case NOTIFICATION_FOCUS_ENTER: {
if (!caret_blink_enabled) {
draw_caret = true;
}
+
+ Point2 cursor_pos = Point2(cursor_get_column(), cursor_get_line()) * get_row_height();
+ OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos);
+
if (OS::get_singleton()->has_virtual_keyboard())
OS::get_singleton()->show_virtual_keyboard(get_text(), get_global_rect());
if (raised_from_completion) {
@@ -1206,6 +1213,8 @@ void TextEdit::_notification(int p_what) {
} break;
case NOTIFICATION_FOCUS_EXIT: {
+ OS::get_singleton()->set_ime_position(Point2());
+
if (OS::get_singleton()->has_virtual_keyboard())
OS::get_singleton()->hide_virtual_keyboard();
if (raised_from_completion) {
@@ -4588,7 +4597,7 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_keyword_color", "keyword", "color"), &TextEdit::add_keyword_color);
ClassDB::bind_method(D_METHOD("add_color_region", "begin_key", "end_key", "color", "line_only"), &TextEdit::add_color_region, DEFVAL(false));
ClassDB::bind_method(D_METHOD("clear_colors"), &TextEdit::clear_colors);
- ClassDB::bind_method(D_METHOD("menu_option"), &TextEdit::menu_option);
+ ClassDB::bind_method(D_METHOD("menu_option", "option"), &TextEdit::menu_option);
ClassDB::bind_method(D_METHOD("get_menu:PopupMenu"), &TextEdit::get_menu);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "syntax_highlighting"), "set_syntax_coloring", "is_syntax_coloring_enabled");
diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp
index 33d9b76b70..2912aa82fc 100644
--- a/scene/gui/texture_button.cpp
+++ b/scene/gui/texture_button.cpp
@@ -206,7 +206,7 @@ void TextureButton::_bind_methods() {
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "texture_focused", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_focused_texture", "get_focused_texture");
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "texture_click_mask", PROPERTY_HINT_RESOURCE_TYPE, "BitMap"), "set_click_mask", "get_click_mask");
ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "expand", PROPERTY_HINT_RESOURCE_TYPE, "bool"), "set_expand", "get_expand");
- ADD_PROPERTYNO(PropertyInfo(Variant::INT, "stretch_mode", PROPERTY_HINT_ENUM, "Scale,Tile,Keep,Keep Centered,Keep Aspect,Keep Aspect Centered,Keep Aspect Covered"), "set_stretch_mode", "get_stretch_mode");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "stretch_mode", PROPERTY_HINT_ENUM, "Scale,Tile,Keep,Keep Centered,Keep Aspect,Keep Aspect Centered,Keep Aspect Covered"), "set_stretch_mode", "get_stretch_mode");
BIND_CONSTANT(STRETCH_SCALE);
BIND_CONSTANT(STRETCH_TILE);
diff --git a/scene/gui/texture_progress.cpp b/scene/gui/texture_progress.cpp
index 081c7ddb73..40995b19fa 100644
--- a/scene/gui/texture_progress.cpp
+++ b/scene/gui/texture_progress.cpp
@@ -242,14 +242,14 @@ Point2 TextureProgress::get_radial_center_offset() {
void TextureProgress::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_under_texture", "tex"), &TextureProgress::set_under_texture);
- ClassDB::bind_method(D_METHOD("get_under_texture"), &TextureProgress::get_under_texture);
+ ClassDB::bind_method(D_METHOD("set_under_texture", "tex:Texture"), &TextureProgress::set_under_texture);
+ ClassDB::bind_method(D_METHOD("get_under_texture:Texture"), &TextureProgress::get_under_texture);
- ClassDB::bind_method(D_METHOD("set_progress_texture", "tex"), &TextureProgress::set_progress_texture);
- ClassDB::bind_method(D_METHOD("get_progress_texture"), &TextureProgress::get_progress_texture);
+ ClassDB::bind_method(D_METHOD("set_progress_texture", "tex:Texture"), &TextureProgress::set_progress_texture);
+ ClassDB::bind_method(D_METHOD("get_progress_texture:Texture"), &TextureProgress::get_progress_texture);
- ClassDB::bind_method(D_METHOD("set_over_texture", "tex"), &TextureProgress::set_over_texture);
- ClassDB::bind_method(D_METHOD("get_over_texture"), &TextureProgress::get_over_texture);
+ ClassDB::bind_method(D_METHOD("set_over_texture", "tex:Texture"), &TextureProgress::set_over_texture);
+ ClassDB::bind_method(D_METHOD("get_over_texture:Texture"), &TextureProgress::get_over_texture);
ClassDB::bind_method(D_METHOD("set_fill_mode", "mode"), &TextureProgress::set_fill_mode);
ClassDB::bind_method(D_METHOD("get_fill_mode"), &TextureProgress::get_fill_mode);
diff --git a/scene/gui/texture_rect.cpp b/scene/gui/texture_rect.cpp
index 92a3db6a74..9459002bc0 100644
--- a/scene/gui/texture_rect.cpp
+++ b/scene/gui/texture_rect.cpp
@@ -101,8 +101,8 @@ Size2 TextureRect::get_minimum_size() const {
}
void TextureRect::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_texture", "texture"), &TextureRect::set_texture);
- ClassDB::bind_method(D_METHOD("get_texture"), &TextureRect::get_texture);
+ ClassDB::bind_method(D_METHOD("set_texture", "texture:Texture"), &TextureRect::set_texture);
+ ClassDB::bind_method(D_METHOD("get_texture:Texture"), &TextureRect::get_texture);
ClassDB::bind_method(D_METHOD("set_expand", "enable"), &TextureRect::set_expand);
ClassDB::bind_method(D_METHOD("has_expand"), &TextureRect::has_expand);
ClassDB::bind_method(D_METHOD("set_stretch_mode", "stretch_mode"), &TextureRect::set_stretch_mode);
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index d8788b4eca..1456ab51c0 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "tree.h"
-#include "global_config.h"
#include "os/input.h"
#include "os/keyboard.h"
#include "os/os.h"
#include "print_string.h"
+#include "project_settings.h"
#include "scene/main/viewport.h"
void TreeItem::move_to_top() {
@@ -70,7 +70,7 @@ Size2 TreeItem::Cell::get_icon_size() const {
return icon_region.size;
}
-void TreeItem::Cell::draw_icon(const RID &p_where, const Point2 &p_pos, const Size2 &p_size) const {
+void TreeItem::Cell::draw_icon(const RID &p_where, const Point2 &p_pos, const Size2 &p_size, const Color &p_color) const {
if (icon.is_null())
return;
@@ -79,10 +79,10 @@ void TreeItem::Cell::draw_icon(const RID &p_where, const Point2 &p_pos, const Si
if (icon_region == Rect2i()) {
- icon->draw_rect_region(p_where, Rect2(p_pos, dsize), Rect2(Point2(), icon->get_size()));
+ icon->draw_rect_region(p_where, Rect2(p_pos, dsize), Rect2(Point2(), icon->get_size()), p_color);
} else {
- icon->draw_rect_region(p_where, Rect2(p_pos, dsize), icon_region);
+ icon->draw_rect_region(p_where, Rect2(p_pos, dsize), icon_region, p_color);
}
}
@@ -203,6 +203,19 @@ Rect2 TreeItem::get_icon_region(int p_column) const {
return cells[p_column].icon_region;
}
+void TreeItem::set_icon_color(int p_column, const Color &p_icon_color) {
+
+ ERR_FAIL_INDEX(p_column, cells.size());
+ cells[p_column].icon_color = p_icon_color;
+ _changed_notify(p_column);
+}
+
+Color TreeItem::get_icon_color(int p_column) const {
+
+ ERR_FAIL_INDEX_V(p_column, cells.size(), Color());
+ return cells[p_column].icon_color;
+}
+
void TreeItem::set_icon_max_width(int p_column, int p_max) {
ERR_FAIL_INDEX(p_column, cells.size());
@@ -697,7 +710,7 @@ void TreeItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_next_visible:TreeItem"), &TreeItem::get_next_visible);
ClassDB::bind_method(D_METHOD("get_prev_visible:TreeItem"), &TreeItem::get_prev_visible);
- ClassDB::bind_method(D_METHOD("remove_child:TreeItem", "child"), &TreeItem::_remove_child);
+ ClassDB::bind_method(D_METHOD("remove_child", "child"), &TreeItem::_remove_child);
ClassDB::bind_method(D_METHOD("set_selectable", "column", "selectable"), &TreeItem::set_selectable);
ClassDB::bind_method(D_METHOD("is_selectable", "column"), &TreeItem::is_selectable);
@@ -933,7 +946,7 @@ int Tree::get_item_height(TreeItem *p_item) const {
return height;
}
-void Tree::draw_item_rect(const TreeItem::Cell &p_cell, const Rect2i &p_rect, const Color &p_color) {
+void Tree::draw_item_rect(const TreeItem::Cell &p_cell, const Rect2i &p_rect, const Color &p_color, const Color &p_icon_color) {
Rect2i rect = p_rect;
Ref<Font> font = cache.font;
@@ -972,7 +985,7 @@ void Tree::draw_item_rect(const TreeItem::Cell &p_cell, const Rect2i &p_rect, co
bmsize.width = p_cell.icon_max_w;
}
- p_cell.draw_icon(ci, rect.position + Size2i(0, Math::floor((real_t)(rect.size.y - bmsize.y) / 2)), bmsize);
+ p_cell.draw_icon(ci, rect.position + Size2i(0, Math::floor((real_t)(rect.size.y - bmsize.y) / 2)), bmsize, p_icon_color);
rect.position.x += bmsize.x + cache.hseparation;
rect.size.x -= bmsize.x + cache.hseparation;
}
@@ -1176,6 +1189,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
}
Color col = p_item->cells[i].custom_color ? p_item->cells[i].color : get_color(p_item->cells[i].selected ? "font_color_selected" : "font_color");
+ Color icon_col = p_item->cells[i].icon_color;
Point2i text_pos = item_rect.position;
text_pos.y += Math::floor((item_rect.size.y - font->get_height()) / 2) + font_ascent;
@@ -1184,7 +1198,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
case TreeItem::CELL_MODE_STRING: {
- draw_item_rect(p_item->cells[i], item_rect, col);
+ draw_item_rect(p_item->cells[i], item_rect, col, icon_col);
} break;
case TreeItem::CELL_MODE_CHECK: {
@@ -1195,9 +1209,9 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (p_item->cells[i].checked) {
- checked->draw(ci, check_ofs);
+ checked->draw(ci, check_ofs, icon_col);
} else {
- unchecked->draw(ci, check_ofs);
+ unchecked->draw(ci, check_ofs, icon_col);
}
int check_w = checked->get_width() + cache.hseparation;
@@ -1207,7 +1221,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
item_rect.size.x -= check_w;
item_rect.position.x += check_w;
- draw_item_rect(p_item->cells[i], item_rect, col);
+ draw_item_rect(p_item->cells[i], item_rect, col, icon_col);
//font->draw( ci, text_pos, p_item->cells[i].text, col,item_rect.size.x-check_w );
@@ -1237,7 +1251,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
arrow_pos.x += item_rect.size.x - downarrow->get_width();
arrow_pos.y += Math::floor(((item_rect.size.y - downarrow->get_height())) / 2.0);
- downarrow->draw(ci, arrow_pos);
+ downarrow->draw(ci, arrow_pos, icon_col);
} else {
Ref<Texture> updown = cache.updown;
@@ -1257,7 +1271,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
updown_pos.x += item_rect.size.x - updown->get_width();
updown_pos.y += Math::floor(((item_rect.size.y - updown->get_height())) / 2.0);
- updown->draw(ci, updown_pos);
+ updown->draw(ci, updown_pos, icon_col);
}
} break;
@@ -1274,7 +1288,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
Point2i icon_ofs = (item_rect.size - icon_size) / 2;
icon_ofs += item_rect.position;
- draw_texture_rect(p_item->cells[i].icon, Rect2(icon_ofs, icon_size));
+ draw_texture_rect(p_item->cells[i].icon, Rect2(icon_ofs, icon_size), false, icon_col);
//p_item->cells[i].icon->draw(ci, icon_ofs);
} break;
@@ -1291,7 +1305,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (!p_item->cells[i].editable) {
- draw_item_rect(p_item->cells[i], item_rect, col);
+ draw_item_rect(p_item->cells[i], item_rect, col, icon_col);
break;
}
@@ -1319,7 +1333,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
ir.position += cache.custom_button->get_offset();
}
- draw_item_rect(p_item->cells[i], ir, col);
+ draw_item_rect(p_item->cells[i], ir, col, icon_col);
downarrow->draw(ci, arrow_pos);
@@ -1953,6 +1967,14 @@ void Tree::text_editor_enter(String p_text) {
c.val = evaluator->eval(p_text);
else
c.val = p_text.to_double();
+
+ if (c.step > 0)
+ c.val = Math::stepify(c.val, c.step);
+ if (c.val < c.min)
+ c.val = c.min;
+ else if (c.val > c.max)
+ c.val = c.max;
+
} break;
default: { ERR_FAIL(); }
}
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 59e35bb230..694f91f9a6 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -89,6 +89,7 @@ private:
Color bg_color;
bool custom_button;
bool expand_right;
+ Color icon_color;
TextAlign text_align;
@@ -133,10 +134,11 @@ private:
icon_max_w = 0;
text_align = ALIGN_LEFT;
expand_right = false;
+ icon_color = Color(1, 1, 1);
}
Size2 get_icon_size() const;
- void draw_icon(const RID &p_where, const Point2 &p_pos, const Size2 &p_size = Size2()) const;
+ void draw_icon(const RID &p_where, const Point2 &p_pos, const Size2 &p_size = Size2(), const Color &p_color = Color()) const;
};
Vector<Cell> cells;
@@ -193,6 +195,9 @@ public:
void set_icon_region(int p_column, const Rect2 &p_icon_region);
Rect2 get_icon_region(int p_column) const;
+ void set_icon_color(int p_column, const Color &p_icon_color);
+ Color get_icon_color(int p_column) const;
+
void set_icon_max_width(int p_column, int p_max);
int get_icon_max_width(int p_column) const;
@@ -361,7 +366,7 @@ private:
int compute_item_height(TreeItem *p_item) const;
int get_item_height(TreeItem *p_item) const;
//void draw_item_text(String p_text,const Ref<Texture>& p_icon,int p_icon_max_w,bool p_tool,Rect2i p_rect,const Color& p_color);
- void draw_item_rect(const TreeItem::Cell &p_cell, const Rect2i &p_rect, const Color &p_color);
+ void draw_item_rect(const TreeItem::Cell &p_cell, const Rect2i &p_rect, const Color &p_color, const Color &p_icon_color);
int draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 &p_draw_size, TreeItem *p_item);
void select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_col, TreeItem *p_prev = NULL, bool *r_in_range = NULL, bool p_force_deselect = false);
int propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool p_doubleclick, TreeItem *p_item, int p_button, const Ref<InputEventWithModifiers> &p_mod);
diff --git a/scene/io/resource_format_image.cpp b/scene/io/resource_format_image.cpp
index 6c0a6128d2..04b6177c3c 100644
--- a/scene/io/resource_format_image.cpp
+++ b/scene/io/resource_format_image.cpp
@@ -30,9 +30,9 @@
#include "resource_format_image.h"
#if 0
-#include "global_config.h"
#include "io/image_loader.h"
#include "os/os.h"
+#include "project_settings.h"
#include "scene/resources/texture.h"
RES ResourceFormatLoaderImage::load(const String &p_path, const String& p_original_path, Error *r_error) {
@@ -128,7 +128,7 @@ RES ResourceFormatLoaderImage::load(const String &p_path, const String& p_origin
if (max_texture_size && (image.get_width() > max_texture_size || image.get_height() > max_texture_size)) {
- if (bool(GlobalConfig::get_singleton()->get("debug/image_loader/max_texture_size_alert"))) {
+ if (bool(ProjectSettings::get_singleton()->get("debug/image_loader/max_texture_size_alert"))) {
OS::get_singleton()->alert("Texture is too large: '"+p_path+"', at "+itos(image.get_width())+"x"+itos(image.get_height())+". Max allowed size is: "+itos(max_texture_size)+"x"+itos(max_texture_size)+".","BAD ARTIST, NO COOKIE!");
}
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 0c65c44392..c3849f79df 100755
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -37,7 +37,6 @@
#include "viewport.h"
VARIANT_ENUM_CAST(Node::PauseMode);
-VARIANT_ENUM_CAST(Node::NetworkMode);
VARIANT_ENUM_CAST(Node::RPCMode);
void Node::_notification(int p_notification) {
@@ -77,16 +76,6 @@ void Node::_notification(int p_notification) {
data.pause_owner = this;
}
- if (data.network_mode == NETWORK_MODE_INHERIT) {
-
- if (data.parent)
- data.network_owner = data.parent->data.network_owner;
- else
- data.network_owner = NULL;
- } else {
- data.network_owner = this;
- }
-
if (data.input)
add_to_group("_vp_input" + itos(get_viewport()->get_instance_ID()));
if (data.unhandled_input)
@@ -108,7 +97,6 @@ void Node::_notification(int p_notification) {
remove_from_group("_vp_unhandled_key_input" + itos(get_viewport()->get_instance_ID()));
data.pause_owner = NULL;
- data.network_owner = NULL;
if (data.path_cache) {
memdelete(data.path_cache);
data.path_cache = NULL;
@@ -323,6 +311,11 @@ void Node::move_child(Node *p_child, int p_pos) {
ERR_FAIL_COND(data.blocked > 0);
}
+ // Specifying one place beyond the end
+ // means the same as moving to the last position
+ if (p_pos == data.children.size())
+ p_pos--;
+
if (p_child->data.pos == p_pos)
return; //do nothing
@@ -472,69 +465,28 @@ void Node::_propagate_pause_owner(Node *p_owner) {
}
}
-void Node::set_network_mode(NetworkMode p_mode) {
+void Node::set_network_master(int p_peer_id, bool p_recursive) {
- if (data.network_mode == p_mode)
- return;
+ data.network_master = p_peer_id;
- bool prev_inherits = data.network_mode == NETWORK_MODE_INHERIT;
- data.network_mode = p_mode;
- if (!is_inside_tree())
- return; //pointless
- if ((data.network_mode == NETWORK_MODE_INHERIT) == prev_inherits)
- return; ///nothing changed
-
- Node *owner = NULL;
-
- if (data.network_mode == NETWORK_MODE_INHERIT) {
+ if (p_recursive) {
+ for (int i = 0; i < data.children.size(); i++) {
- if (data.parent)
- owner = data.parent->data.network_owner;
- } else {
- owner = this;
+ data.children[i]->set_network_master(p_peer_id, true);
+ }
}
-
- _propagate_network_owner(owner);
}
-Node::NetworkMode Node::get_network_mode() const {
+int Node::get_network_master() const {
- return data.network_mode;
+ return data.network_master;
}
bool Node::is_network_master() const {
ERR_FAIL_COND_V(!is_inside_tree(), false);
- switch (data.network_mode) {
- case NETWORK_MODE_INHERIT: {
-
- if (data.network_owner)
- return data.network_owner->is_network_master();
- else
- return get_tree()->is_network_server();
- } break;
- case NETWORK_MODE_MASTER: {
-
- return true;
- } break;
- case NETWORK_MODE_SLAVE: {
- return false;
- } break;
- }
-
- return false;
-}
-
-void Node::_propagate_network_owner(Node *p_owner) {
-
- if (data.network_mode != NETWORK_MODE_INHERIT)
- return;
- data.network_owner = p_owner;
- for (int i = 0; i < data.children.size(); i++) {
-
- data.children[i]->_propagate_network_owner(p_owner);
- }
+ return get_tree()->get_network_unique_id() == data.network_master;
}
/***** RPC CONFIG ********/
@@ -962,7 +914,7 @@ void Node::rset_unreliable_id(int p_peer_id, const StringName &p_property, const
//////////// end of rpc
-bool Node::can_call_rpc(const StringName &p_method) const {
+bool Node::can_call_rpc(const StringName &p_method, int p_from) const {
const Map<StringName, RPCMode>::Element *E = data.rpc_methods.find(p_method);
if (E) {
@@ -982,7 +934,7 @@ bool Node::can_call_rpc(const StringName &p_method) const {
return is_network_master();
} break;
case RPC_MODE_SLAVE: {
- return !is_network_master();
+ return !is_network_master() && p_from == get_network_master();
} break;
}
}
@@ -1006,16 +958,16 @@ bool Node::can_call_rpc(const StringName &p_method) const {
return is_network_master();
} break;
case ScriptInstance::RPC_MODE_SLAVE: {
- return !is_network_master();
+ return !is_network_master() && p_from == get_network_master();
} break;
}
}
- ERR_PRINTS("RPC on unauthorized method attempted: " + String(p_method) + " on base: " + String(Variant(this)));
+ ERR_PRINTS("RPC from " + itos(p_from) + " on unauthorized method attempted: " + String(p_method) + " on base: " + String(Variant(this)));
return false;
}
-bool Node::can_call_rset(const StringName &p_property) const {
+bool Node::can_call_rset(const StringName &p_property, int p_from) const {
const Map<StringName, RPCMode>::Element *E = data.rpc_properties.find(p_property);
if (E) {
@@ -1035,7 +987,7 @@ bool Node::can_call_rset(const StringName &p_property) const {
return is_network_master();
} break;
case RPC_MODE_SLAVE: {
- return !is_network_master();
+ return !is_network_master() && p_from == get_network_master();
} break;
}
}
@@ -1059,12 +1011,12 @@ bool Node::can_call_rset(const StringName &p_property) const {
return is_network_master();
} break;
case ScriptInstance::RPC_MODE_SLAVE: {
- return !is_network_master();
+ return !is_network_master() && p_from == get_network_master();
} break;
}
}
- ERR_PRINTS("RSET on unauthorized property attempted: " + String(p_property) + " on base: " + String(Variant(this)));
+ ERR_PRINTS("RSET from " + itos(p_from) + " on unauthorized property attempted: " + String(p_property) + " on base: " + String(Variant(this)));
return false;
}
@@ -1311,7 +1263,7 @@ String Node::_generate_serial_child_name(Node *p_child) {
name = p_child->get_class();
// Adjust casing according to project setting. The current type name is expected to be in PascalCase.
- switch (GlobalConfig::get_singleton()->get("node/name_casing").operator int()) {
+ switch (ProjectSettings::get_singleton()->get("node/name_casing").operator int()) {
case NAME_CASING_PASCAL_CASE:
break;
case NAME_CASING_CAMEL_CASE:
@@ -2765,9 +2717,9 @@ void Node::request_ready() {
void Node::_bind_methods() {
GLOBAL_DEF("node/name_num_separator", 0);
- GlobalConfig::get_singleton()->set_custom_property_info("node/name_num_separator", PropertyInfo(Variant::INT, "node/name_num_separator", PROPERTY_HINT_ENUM, "None,Space,Underscore,Dash"));
+ ProjectSettings::get_singleton()->set_custom_property_info("node/name_num_separator", PropertyInfo(Variant::INT, "node/name_num_separator", PROPERTY_HINT_ENUM, "None,Space,Underscore,Dash"));
GLOBAL_DEF("node/name_casing", NAME_CASING_PASCAL_CASE);
- GlobalConfig::get_singleton()->set_custom_property_info("node/name_casing", PropertyInfo(Variant::INT, "node/name_casing", PROPERTY_HINT_ENUM, "PascalCase,camelCase,snake_case"));
+ ProjectSettings::get_singleton()->set_custom_property_info("node/name_casing", PropertyInfo(Variant::INT, "node/name_casing", PROPERTY_HINT_ENUM, "PascalCase,camelCase,snake_case"));
ClassDB::bind_method(D_METHOD("_add_child_below_node", "node:Node", "child_node:Node", "legible_unique_name"), &Node::add_child_below_node, DEFVAL(false));
@@ -2839,14 +2791,14 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_scene_instance_load_placeholder", "load_placeholder"), &Node::set_scene_instance_load_placeholder);
ClassDB::bind_method(D_METHOD("get_scene_instance_load_placeholder"), &Node::get_scene_instance_load_placeholder);
- ClassDB::bind_method(D_METHOD("get_viewport"), &Node::get_viewport);
+ ClassDB::bind_method(D_METHOD("get_viewport:Viewport"), &Node::get_viewport);
ClassDB::bind_method(D_METHOD("queue_free"), &Node::queue_delete);
ClassDB::bind_method(D_METHOD("request_ready"), &Node::request_ready);
- ClassDB::bind_method(D_METHOD("set_network_mode", "mode"), &Node::set_network_mode);
- ClassDB::bind_method(D_METHOD("get_network_mode"), &Node::get_network_mode);
+ ClassDB::bind_method(D_METHOD("set_network_master", "id", "recursive"), &Node::set_network_master, DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("get_network_master"), &Node::get_network_master);
ClassDB::bind_method(D_METHOD("is_network_master"), &Node::is_network_master);
@@ -2902,10 +2854,6 @@ void Node::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_INTERNAL_PROCESS);
BIND_CONSTANT(NOTIFICATION_INTERNAL_FIXED_PROCESS);
- BIND_CONSTANT(NETWORK_MODE_INHERIT);
- BIND_CONSTANT(NETWORK_MODE_MASTER);
- BIND_CONSTANT(NETWORK_MODE_SLAVE);
-
BIND_CONSTANT(RPC_MODE_DISABLED);
BIND_CONSTANT(RPC_MODE_REMOTE);
BIND_CONSTANT(RPC_MODE_SYNC);
@@ -2947,7 +2895,7 @@ void Node::_bind_methods() {
}
String Node::_get_name_num_separator() {
- switch (GlobalConfig::get_singleton()->get("node/name_num_separator").operator int()) {
+ switch (ProjectSettings::get_singleton()->get("node/name_num_separator").operator int()) {
case 0: return "";
case 1: return " ";
case 2: return "_";
@@ -2977,8 +2925,7 @@ Node::Node() {
data.unhandled_key_input = false;
data.pause_mode = PAUSE_MODE_INHERIT;
data.pause_owner = NULL;
- data.network_mode = NETWORK_MODE_INHERIT;
- data.network_owner = NULL;
+ data.network_master = 1; //server by default
data.path_cache = NULL;
data.parent_owned = false;
data.in_constructor = true;
diff --git a/scene/main/node.h b/scene/main/node.h
index ffd2b7ce5f..1794cce9f6 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -31,10 +31,10 @@
#define NODE_H
#include "class_db.h"
-#include "global_config.h"
#include "map.h"
#include "object.h"
#include "path_db.h"
+#include "project_settings.h"
#include "scene/main/scene_tree.h"
#include "script_language.h"
@@ -61,13 +61,6 @@ public:
DUPLICATE_USE_INSTANCING = 8
};
- enum NetworkMode {
-
- NETWORK_MODE_INHERIT,
- NETWORK_MODE_MASTER,
- NETWORK_MODE_SLAVE
- };
-
enum RPCMode {
RPC_MODE_DISABLED, //no rpc for this method, calls to this will be blocked (default)
@@ -122,8 +115,7 @@ private:
PauseMode pause_mode;
Node *pause_owner;
- NetworkMode network_mode;
- Node *network_owner;
+ int network_master;
Map<StringName, RPCMode> rpc_methods;
Map<StringName, RPCMode> rpc_properties;
@@ -173,7 +165,6 @@ private:
void _propagate_validate_owner();
void _print_stray_nodes();
void _propagate_pause_owner(Node *p_owner);
- void _propagate_network_owner(Node *p_owner);
Array _get_node_and_resource(const NodePath &p_path);
void _duplicate_signals(const Node *p_original, Node *p_copy) const;
@@ -393,8 +384,8 @@ public:
bool is_displayed_folded() const;
/* NETWORK */
- void set_network_mode(NetworkMode p_mode);
- NetworkMode get_network_mode() const;
+ void set_network_master(int p_peer_id, bool p_recursive = true);
+ int get_network_master() const;
bool is_network_master() const;
void rpc_config(const StringName &p_method, RPCMode p_mode); // config a local method for RPC
@@ -414,8 +405,8 @@ public:
void rsetp(int p_peer_id, bool p_unreliable, const StringName &p_property, const Variant &p_value);
- bool can_call_rpc(const StringName &p_method) const;
- bool can_call_rset(const StringName &p_property) const;
+ bool can_call_rpc(const StringName &p_method, int p_from) const;
+ bool can_call_rset(const StringName &p_property, int p_from) const;
Node();
~Node();
diff --git a/scene/main/resource_preloader.cpp b/scene/main/resource_preloader.cpp
index ae323ba021..febb95a181 100644
--- a/scene/main/resource_preloader.cpp
+++ b/scene/main/resource_preloader.cpp
@@ -153,11 +153,11 @@ void ResourcePreloader::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_resources"), &ResourcePreloader::_set_resources);
ClassDB::bind_method(D_METHOD("_get_resources"), &ResourcePreloader::_get_resources);
- ClassDB::bind_method(D_METHOD("add_resource", "name", "resource"), &ResourcePreloader::add_resource);
+ ClassDB::bind_method(D_METHOD("add_resource", "name", "resource:Resource"), &ResourcePreloader::add_resource);
ClassDB::bind_method(D_METHOD("remove_resource", "name"), &ResourcePreloader::remove_resource);
ClassDB::bind_method(D_METHOD("rename_resource", "name", "newname"), &ResourcePreloader::rename_resource);
ClassDB::bind_method(D_METHOD("has_resource", "name"), &ResourcePreloader::has_resource);
- ClassDB::bind_method(D_METHOD("get_resource", "name"), &ResourcePreloader::get_resource);
+ ClassDB::bind_method(D_METHOD("get_resource:Resource", "name"), &ResourcePreloader::get_resource);
ClassDB::bind_method(D_METHOD("get_resource_list"), &ResourcePreloader::_get_resource_list);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "resources", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_resources", "_get_resources");
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 479abccda6..48e6a44745 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -29,12 +29,12 @@
/*************************************************************************/
#include "scene_tree.h"
-#include "global_config.h"
#include "message_queue.h"
#include "node.h"
#include "os/keyboard.h"
#include "os/os.h"
#include "print_string.h"
+#include "project_settings.h"
#include <stdio.h>
//#include "servers/spatial_sound_2d_server.h"
@@ -614,7 +614,7 @@ bool SceneTree::idle(float p_time) {
if (is_editor_hint()) {
//simple hack to reload fallback environment if it changed from editor
- String env_path = GlobalConfig::get_singleton()->get("rendering/viewport/default_environment");
+ String env_path = ProjectSettings::get_singleton()->get("rendering/environment/default_environment");
env_path = env_path.strip_edges(); //user may have added a space or two
String cpath;
Ref<Environment> fallback = get_root()->get_world()->get_fallback_environment();
@@ -1153,7 +1153,7 @@ void SceneTree::_update_root_rect() {
if (stretch_mode == STRETCH_MODE_DISABLED) {
- root->set_size(last_screen_size);
+ root->set_size((last_screen_size / stretch_shrink).floor());
root->set_attach_to_screen_rect(Rect2(Point2(), last_screen_size));
root->set_size_override_stretch(false);
root->set_size_override(false, Size2());
@@ -1231,15 +1231,15 @@ void SceneTree::_update_root_rect() {
switch (stretch_mode) {
case STRETCH_MODE_2D: {
- root->set_size(screen_size);
+ root->set_size((screen_size / stretch_shrink).floor());
root->set_attach_to_screen_rect(Rect2(margin, screen_size));
root->set_size_override_stretch(true);
- root->set_size_override(true, viewport_size);
+ root->set_size_override(true, (viewport_size / stretch_shrink).floor());
} break;
case STRETCH_MODE_VIEWPORT: {
- root->set_size(viewport_size);
+ root->set_size((viewport_size / stretch_shrink).floor());
root->set_attach_to_screen_rect(Rect2(margin, screen_size));
root->set_size_override_stretch(false);
root->set_size_override(false, Size2());
@@ -1248,11 +1248,12 @@ void SceneTree::_update_root_rect() {
}
}
-void SceneTree::set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 p_minsize) {
+void SceneTree::set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 p_minsize, int p_shrink) {
stretch_mode = p_mode;
stretch_aspect = p_aspect;
stretch_min = p_minsize;
+ stretch_shrink = p_shrink;
_update_root_rect();
}
@@ -1763,6 +1764,16 @@ int SceneTree::get_network_unique_id() const {
return network_peer->get_unique_id();
}
+Vector<int> SceneTree::get_network_connected_peers() const {
+ ERR_FAIL_COND_V(!network_peer.is_valid(), Vector<int>());
+
+ Vector<int> ret;
+ for (Set<int>::Element *E = connected_peers.front(); E; E = E->next()) {
+ ret.push_back(E->get());
+ }
+
+ return ret;
+}
void SceneTree::set_refuse_new_network_connections(bool p_refuse) {
ERR_FAIL_COND(!network_peer.is_valid());
network_peer->set_refuse_new_connections(p_refuse);
@@ -1973,6 +1984,7 @@ void SceneTree::_network_process_packet(int p_from, const uint8_t *p_packet, int
Node *node = NULL;
if (target & 0x80000000) {
+ //use full path (not cached yet)
int ofs = target & 0x7FFFFFFF;
ERR_FAIL_COND(ofs >= p_packet_len);
@@ -1988,7 +2000,7 @@ void SceneTree::_network_process_packet(int p_from, const uint8_t *p_packet, int
ERR_FAIL_COND(node == NULL);
}
} else {
-
+ //use cached path
int id = target;
Map<int, PathGetCache>::Element *E = path_get_cache.find(p_from);
@@ -2023,7 +2035,7 @@ void SceneTree::_network_process_packet(int p_from, const uint8_t *p_packet, int
if (packet_type == NETWORK_COMMAND_REMOTE_CALL) {
- if (!node->can_call_rpc(name))
+ if (!node->can_call_rpc(name, p_from))
return;
int ofs = len_end + 1;
@@ -2060,7 +2072,7 @@ void SceneTree::_network_process_packet(int p_from, const uint8_t *p_packet, int
} else {
- if (!node->can_call_rset(name))
+ if (!node->can_call_rset(name, p_from))
return;
int ofs = len_end + 1;
@@ -2181,8 +2193,8 @@ void SceneTree::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_debugging_navigation_hint"), &SceneTree::is_debugging_navigation_hint);
#ifdef TOOLS_ENABLED
- ClassDB::bind_method(D_METHOD("set_edited_scene_root", "scene"), &SceneTree::set_edited_scene_root);
- ClassDB::bind_method(D_METHOD("get_edited_scene_root"), &SceneTree::get_edited_scene_root);
+ ClassDB::bind_method(D_METHOD("set_edited_scene_root", "scene:Node"), &SceneTree::set_edited_scene_root);
+ ClassDB::bind_method(D_METHOD("get_edited_scene_root:Node"), &SceneTree::get_edited_scene_root);
#endif
ClassDB::bind_method(D_METHOD("set_pause", "enable"), &SceneTree::set_pause);
@@ -2196,7 +2208,7 @@ void SceneTree::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_frame"), &SceneTree::get_frame);
ClassDB::bind_method(D_METHOD("quit"), &SceneTree::quit);
- ClassDB::bind_method(D_METHOD("set_screen_stretch", "mode", "aspect", "minsize"), &SceneTree::set_screen_stretch);
+ ClassDB::bind_method(D_METHOD("set_screen_stretch", "mode", "aspect", "minsize", "shrink"), &SceneTree::set_screen_stretch, DEFVAL(1));
ClassDB::bind_method(D_METHOD("queue_delete", "obj"), &SceneTree::queue_delete);
@@ -2236,6 +2248,7 @@ void SceneTree::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_network_peer", "peer:NetworkedMultiplayerPeer"), &SceneTree::set_network_peer);
ClassDB::bind_method(D_METHOD("is_network_server"), &SceneTree::is_network_server);
ClassDB::bind_method(D_METHOD("has_network_peer"), &SceneTree::has_network_peer);
+ ClassDB::bind_method(D_METHOD("get_network_connected_peers"), &SceneTree::get_network_connected_peers);
ClassDB::bind_method(D_METHOD("get_network_unique_id"), &SceneTree::get_network_unique_id);
ClassDB::bind_method(D_METHOD("set_refuse_new_network_connections", "refuse"), &SceneTree::set_refuse_new_network_connections);
ClassDB::bind_method(D_METHOD("is_refusing_new_network_connections"), &SceneTree::is_refusing_new_network_connections);
@@ -2305,11 +2318,11 @@ SceneTree::SceneTree() {
debug_collisions_hint = false;
debug_navigation_hint = false;
#endif
- debug_collisions_color = GLOBAL_DEF("debug/collision/shape_color", Color(0.0, 0.6, 0.7, 0.5));
- debug_collision_contact_color = GLOBAL_DEF("debug/collision/contact_color", Color(1.0, 0.2, 0.1, 0.8));
- debug_navigation_color = GLOBAL_DEF("debug/navigation/geometry_color", Color(0.1, 1.0, 0.7, 0.4));
- debug_navigation_disabled_color = GLOBAL_DEF("debug/navigation/disabled_geometry_color", Color(1.0, 0.7, 0.1, 0.4));
- collision_debug_contacts = GLOBAL_DEF("debug/collision/max_contacts_displayed", 10000);
+ debug_collisions_color = GLOBAL_DEF("debug/shapes/collision/shape_color", Color(0.0, 0.6, 0.7, 0.5));
+ debug_collision_contact_color = GLOBAL_DEF("debug/shapes/collision/contact_color", Color(1.0, 0.2, 0.1, 0.8));
+ debug_navigation_color = GLOBAL_DEF("debug/shapes/navigation/geometry_color", Color(0.1, 1.0, 0.7, 0.4));
+ debug_navigation_disabled_color = GLOBAL_DEF("debug/shapes/navigation/disabled_geometry_color", Color(1.0, 0.7, 0.1, 0.4));
+ collision_debug_contacts = GLOBAL_DEF("debug/shapes/collision/max_contacts_displayed", 10000);
tree_version = 1;
fixed_process_time = 1;
@@ -2336,12 +2349,16 @@ SceneTree::SceneTree() {
root->set_as_audio_listener_2d(true);
current_scene = NULL;
- int ref_atlas_size = GLOBAL_DEF("rendering/reflections/atlas_size", 2048);
- int ref_atlas_subdiv = GLOBAL_DEF("rendering/reflections/atlas_subdiv", 8);
- int msaa_mode = GLOBAL_DEF("rendering/quality/msaa", 0);
- GlobalConfig::get_singleton()->set_custom_property_info("rendering/quality/msaa", PropertyInfo(Variant::INT, "rendering/quality/msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x"));
+ int ref_atlas_size = GLOBAL_DEF("rendering/quality/reflections/atlas_size", 2048);
+ int ref_atlas_subdiv = GLOBAL_DEF("rendering/quality/reflections/atlas_subdiv", 8);
+ int msaa_mode = GLOBAL_DEF("rendering/quality/filters/msaa", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/filters/msaa", PropertyInfo(Variant::INT, "rendering/quality/filters/msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x"));
root->set_msaa(Viewport::MSAA(msaa_mode));
- bool hdr = GLOBAL_DEF("rendering/quality/hdr", true);
+
+ GLOBAL_DEF("rendering/quality/depth/hdr", true);
+ GLOBAL_DEF("rendering/quality/depth/hdr.mobile", false);
+
+ bool hdr = GLOBAL_GET("rendering/quality/depth/hdr");
root->set_hdr(hdr);
VS::get_singleton()->scenario_set_reflection_atlas_size(root->get_world()->get_scenario(), ref_atlas_size, ref_atlas_subdiv);
@@ -2357,9 +2374,9 @@ SceneTree::SceneTree() {
ext_hint += "*." + E->get();
}
//get path
- String env_path = GLOBAL_DEF("rendering/viewport/default_environment", "");
+ String env_path = GLOBAL_DEF("rendering/environment/default_environment", "");
//setup property
- GlobalConfig::get_singleton()->set_custom_property_info("rendering/viewport/default_environment", PropertyInfo(Variant::STRING, "rendering/viewport/default_environment", PROPERTY_HINT_FILE, ext_hint));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/default_environment", PropertyInfo(Variant::STRING, "rendering/viewport/default_environment", PROPERTY_HINT_FILE, ext_hint));
env_path = env_path.strip_edges();
if (env_path != String()) {
Ref<Environment> env = ResourceLoader::load(env_path);
@@ -2368,7 +2385,7 @@ SceneTree::SceneTree() {
} else {
if (is_editor_hint()) {
//file was erased, clear the field.
- GlobalConfig::get_singleton()->set("rendering/viewport/default_environment", "");
+ ProjectSettings::get_singleton()->set("rendering/environment/default_environment", "");
} else {
//file was erased, notify user.
ERR_PRINTS(RTR("Default Environment as specified in Project Setings (Rendering -> Viewport -> Default Environment) could not be loaded."));
@@ -2379,6 +2396,7 @@ SceneTree::SceneTree() {
stretch_mode = STRETCH_MODE_DISABLED;
stretch_aspect = STRETCH_ASPECT_IGNORE;
+ stretch_shrink = 1;
last_screen_size = Size2(OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height);
_update_root_rect();
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index 2ea79bf945..90d42ef01b 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -149,6 +149,7 @@ private:
StretchMode stretch_mode;
StretchAspect stretch_aspect;
Size2i stretch_min;
+ int stretch_shrink;
void _update_root_rect();
@@ -420,7 +421,7 @@ public:
void get_nodes_in_group(const StringName &p_group, List<Node *> *p_list);
bool has_group(const StringName &p_identifier) const;
- void set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 p_minsize);
+ void set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 p_minsize, int p_shrink = 1);
//void change_scene(const String& p_path);
//Node *get_loaded_scene();
@@ -451,6 +452,7 @@ public:
bool is_network_server() const;
bool has_network_peer() const;
int get_network_unique_id() const;
+ Vector<int> get_network_connected_peers() const;
void set_refuse_new_network_connections(bool p_refuse);
bool is_refusing_new_network_connections() const;
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 3a9968d126..76b281ebac 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -48,7 +48,7 @@
#include "scene/main/timer.h"
#include "scene/scene_string_names.h"
-#include "global_config.h"
+#include "project_settings.h"
#include "scene/3d/scenario_fx.h"
void ViewportTexture::setup_local_to_scene() {
@@ -701,6 +701,16 @@ RID Viewport::get_viewport_rid() const {
return viewport;
}
+void Viewport::set_use_arvr(bool p_use_arvr) {
+ arvr = p_use_arvr;
+
+ VS::get_singleton()->viewport_set_use_arvr(viewport, arvr);
+}
+
+bool Viewport::use_arvr() {
+ return arvr;
+}
+
void Viewport::set_size(const Size2 &p_size) {
if (size == p_size.floor())
@@ -2057,6 +2067,10 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
//keyboard focus
//if (from && p_event->is_pressed() && !p_event->get_alt() && !p_event->get_metakey() && !p_event->key->get_command()) {
+ Ref<InputEventKey> k = p_event;
+ //need to check for mods, otherwise any combination of alt/ctrl/shift+<up/down/left/righ/etc> is handled here when it shouldn't be.
+ bool mods = k.is_valid() && (k->get_control() || k->get_alt() || k->get_shift() || k->get_metakey());
+
if (from && p_event->is_pressed()) {
Control *next = NULL;
@@ -2070,22 +2084,22 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
next = from->find_prev_valid_focus();
}
- if (p_event->is_action("ui_up")) {
+ if (!mods && p_event->is_action("ui_up")) {
next = from->_get_focus_neighbour(MARGIN_TOP);
}
- if (p_event->is_action("ui_left")) {
+ if (!mods && p_event->is_action("ui_left")) {
next = from->_get_focus_neighbour(MARGIN_LEFT);
}
- if (p_event->is_action("ui_right")) {
+ if (!mods && p_event->is_action("ui_right")) {
next = from->_get_focus_neighbour(MARGIN_RIGHT);
}
- if (p_event->is_action("ui_down")) {
+ if (!mods && p_event->is_action("ui_down")) {
next = from->_get_focus_neighbour(MARGIN_BOTTOM);
}
@@ -2352,7 +2366,7 @@ void Viewport::unhandled_input(const Ref<InputEvent> &p_event) {
if (physics_object_picking && !get_tree()->input_handled) {
- if (p_event->cast_to<InputEventMouseButton>() || p_event->cast_to<InputEventMouseMotion>() || p_event->cast_to<InputEventScreenDrag>() || p_event->cast_to<InputEventScreenTouch>()) {
+ if (Input::get_singleton()->get_mouse_mode() != Input::MOUSE_MODE_CAPTURED && (p_event->cast_to<InputEventMouseButton>() || p_event->cast_to<InputEventMouseMotion>() || p_event->cast_to<InputEventScreenDrag>() || p_event->cast_to<InputEventScreenTouch>())) {
physics_picking_events.push_back(p_event);
}
}
@@ -2539,6 +2553,9 @@ int Viewport::get_render_info(RenderInfo p_info) {
void Viewport::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_use_arvr", "use"), &Viewport::set_use_arvr);
+ ClassDB::bind_method(D_METHOD("use_arvr"), &Viewport::use_arvr);
+
ClassDB::bind_method(D_METHOD("set_size", "size"), &Viewport::set_size);
ClassDB::bind_method(D_METHOD("get_size"), &Viewport::get_size);
ClassDB::bind_method(D_METHOD("set_world_2d", "world_2d:World2D"), &Viewport::set_world_2d);
@@ -2602,8 +2619,8 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_physics_object_picking"), &Viewport::get_physics_object_picking);
ClassDB::bind_method(D_METHOD("get_viewport_rid"), &Viewport::get_viewport_rid);
- ClassDB::bind_method(D_METHOD("input", "local_event"), &Viewport::input);
- ClassDB::bind_method(D_METHOD("unhandled_input", "local_event"), &Viewport::unhandled_input);
+ ClassDB::bind_method(D_METHOD("input", "local_event:InputEvent"), &Viewport::input);
+ ClassDB::bind_method(D_METHOD("unhandled_input", "local_event:InputEvent"), &Viewport::unhandled_input);
ClassDB::bind_method(D_METHOD("update_worlds"), &Viewport::update_worlds);
@@ -2640,6 +2657,8 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_shadow_atlas_quadrant_subdiv", "quadrant", "subdiv"), &Viewport::set_shadow_atlas_quadrant_subdiv);
ClassDB::bind_method(D_METHOD("get_shadow_atlas_quadrant_subdiv", "quadrant"), &Viewport::get_shadow_atlas_quadrant_subdiv);
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "arvr"), "set_use_arvr", "use_arvr");
+
ADD_PROPERTY(PropertyInfo(Variant::RECT2, "size"), "set_size", "get_size");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "own_world"), "set_use_own_world", "is_using_own_world");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world", PROPERTY_HINT_RESOURCE_TYPE, "World"), "set_world", "get_world");
@@ -2725,6 +2744,7 @@ Viewport::Viewport() {
parent = NULL;
listener = NULL;
camera = NULL;
+ arvr = false;
size_override = false;
size_override_stretch = false;
size_override_size = Size2(1, 1);
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index bd9747d878..83c989db54 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -148,6 +148,8 @@ private:
Listener *listener;
Set<Listener *> listeners;
+ bool arvr;
+
Camera *camera;
Set<Camera *> cameras;
@@ -349,6 +351,9 @@ public:
Listener *get_listener() const;
Camera *get_camera() const;
+ void set_use_arvr(bool p_use_arvr);
+ bool use_arvr();
+
void set_as_audio_listener(bool p_enable);
bool is_audio_listener() const;
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 76e07db93d..f286bfb81a 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "register_scene_types.h"
-#include "global_config.h"
#include "os/os.h"
+#include "project_settings.h"
#include "scene/io/resource_format_image.h"
#include "scene/io/resource_format_wav.h"
@@ -164,7 +164,7 @@
#include "scene/resources/polygon_path_finder.h"
//#include "scene/resources/sample.h"
-//#include "scene/audio/sample_player.h"
+#include "scene/3d/audio_stream_player_3d.h"
#include "scene/resources/material.h"
#include "scene/resources/mesh.h"
#include "scene/resources/room.h"
@@ -199,6 +199,8 @@
#include "scene/3d/camera.h"
#include "scene/3d/listener.h"
+#include "scene/3d/arvr_nodes.h"
+
#include "scene/3d/gi_probe.h"
#include "scene/3d/interpolated_camera.h"
#include "scene/3d/light.h"
@@ -212,7 +214,7 @@
#include "scene/3d/area.h"
-#include "scene/3d/body_shape.h"
+#include "scene/3d/collision_shape.h"
#include "scene/3d/immediate_geometry.h"
#include "scene/3d/multimesh_instance.h"
#include "scene/3d/physics_joint.h"
@@ -271,11 +273,11 @@ void register_scene_types() {
ResourceLoader::add_resource_format_loader(resource_loader_theme);
bool default_theme_hidpi = GLOBAL_DEF("gui/theme/use_hidpi", false);
- GlobalConfig::get_singleton()->set_custom_property_info("gui/theme/use_hidpi", PropertyInfo(Variant::BOOL, "gui/theme/use_hidpi", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
+ ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/use_hidpi", PropertyInfo(Variant::BOOL, "gui/theme/use_hidpi", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
String theme_path = GLOBAL_DEF("gui/theme/custom", "");
- GlobalConfig::get_singleton()->set_custom_property_info("gui/theme/custom", PropertyInfo(Variant::STRING, "gui/theme/custom", PROPERTY_HINT_FILE, "*.tres,*.res", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
+ ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom", PropertyInfo(Variant::STRING, "gui/theme/custom", PROPERTY_HINT_FILE, "*.tres,*.res", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
String font_path = GLOBAL_DEF("gui/theme/custom_font", "");
- GlobalConfig::get_singleton()->set_custom_property_info("gui/theme/custom_font", PropertyInfo(Variant::STRING, "gui/theme/custom_font", PROPERTY_HINT_FILE, "*.tres,*.res,*.font", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
+ ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom_font", PropertyInfo(Variant::STRING, "gui/theme/custom_font", PROPERTY_HINT_FILE, "*.tres,*.res,*.font", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
if (theme_path != String()) {
Ref<Theme> theme = ResourceLoader::load(theme_path);
@@ -405,6 +407,9 @@ void register_scene_types() {
ClassDB::register_virtual_class<VisualInstance>();
ClassDB::register_class<Camera>();
ClassDB::register_class<Listener>();
+ ClassDB::register_class<ARVRCamera>();
+ ClassDB::register_class<ARVRController>();
+ ClassDB::register_class<ARVROrigin>();
ClassDB::register_class<InterpolatedCamera>();
ClassDB::register_class<MeshInstance>();
ClassDB::register_class<ImmediateGeometry>();
@@ -532,8 +537,6 @@ void register_scene_types() {
ClassDB::register_class<SphereMesh>();
ClassDB::register_virtual_class<Material>();
ClassDB::register_class<SpatialMaterial>();
- ClassDB::add_compatibility_class("FixedSpatialMaterial", "SpatialMaterial");
- ClassDB::add_compatibility_class("Mesh", "ArrayMesh");
SceneTree::add_idle_callback(SpatialMaterial::flush_changes);
SpatialMaterial::init_shaders();
@@ -562,6 +565,7 @@ void register_scene_types() {
OS::get_singleton()->yield(); //may take time to init
+ ClassDB::register_class<SpatialVelocityTracker>();
#endif
ClassDB::register_class<World>();
ClassDB::register_class<Environment>();
@@ -598,6 +602,7 @@ void register_scene_types() {
ClassDB::register_class<AudioStreamPlayer>();
ClassDB::register_class<AudioStreamPlayer2D>();
+ ClassDB::register_class<AudioStreamPlayer3D>();
ClassDB::register_virtual_class<VideoStream>();
ClassDB::register_class<AudioStreamSample>();
@@ -628,6 +633,13 @@ void register_scene_types() {
ClassDB::register_class<SceneTree>();
ClassDB::register_virtual_class<SceneTreeTimer>(); //sorry, you can't create it
+#ifndef DISABLE_DEPRECATED
+ ClassDB::add_compatibility_class("ImageSkyBox", "PanoramaSky");
+ ClassDB::add_compatibility_class("FixedSpatialMaterial", "SpatialMaterial");
+ ClassDB::add_compatibility_class("Mesh", "ArrayMesh");
+
+#endif
+
OS::get_singleton()->yield(); //may take time to init
resource_saver_text = memnew(ResourceFormatSaverText);
diff --git a/scene/resources/audio_stream_resampled.cpp b/scene/resources/audio_stream_resampled.cpp
index 213ac4400b..1b1d6f8587 100644
--- a/scene/resources/audio_stream_resampled.cpp
+++ b/scene/resources/audio_stream_resampled.cpp
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "audio_stream_resampled.h"
-#include "global_config.h"
+#include "project_settings.h"
#if 0
int AudioStreamResampled::get_channel_count() const {
diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_sample.cpp
index f12e231074..c8f6007e60 100644
--- a/scene/resources/audio_stream_sample.cpp
+++ b/scene/resources/audio_stream_sample.cpp
@@ -231,7 +231,7 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in
/* some 64-bit fixed point precaches */
- int64_t loop_begin_fp = ((int64_t)len << MIX_FRAC_BITS);
+ int64_t loop_begin_fp = ((int64_t)base->loop_begin << MIX_FRAC_BITS);
int64_t loop_end_fp = ((int64_t)base->loop_end << MIX_FRAC_BITS);
int64_t length_fp = ((int64_t)len << MIX_FRAC_BITS);
int64_t begin_limit = (base->loop_mode != AudioStreamSample::LOOP_DISABLED) ? loop_begin_fp : 0;
diff --git a/scene/resources/bit_mask.cpp b/scene/resources/bit_mask.cpp
index a473067937..73a759278b 100644
--- a/scene/resources/bit_mask.cpp
+++ b/scene/resources/bit_mask.cpp
@@ -170,7 +170,7 @@ Dictionary BitMap::_get_data() const {
void BitMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("create", "size"), &BitMap::create);
- ClassDB::bind_method(D_METHOD("create_from_image_alpha", "image"), &BitMap::create_from_image_alpha);
+ ClassDB::bind_method(D_METHOD("create_from_image_alpha", "image:Image"), &BitMap::create_from_image_alpha);
ClassDB::bind_method(D_METHOD("set_bit", "pos", "bit"), &BitMap::set_bit);
ClassDB::bind_method(D_METHOD("get_bit", "pos"), &BitMap::get_bit);
diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp
index 338311b87b..fe0759fcba 100644
--- a/scene/resources/curve.cpp
+++ b/scene/resources/curve.cpp
@@ -1188,7 +1188,7 @@ void Curve2D::_set_data(const Dictionary &p_data) {
baked_cache_dirty = true;
}
-PoolVector2Array Curve2D::tesselate(int p_max_stages, float p_tolerance) const {
+PoolVector2Array Curve2D::tessellate(int p_max_stages, float p_tolerance) const {
PoolVector2Array tess;
@@ -1250,7 +1250,7 @@ void Curve2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_baked_length"), &Curve2D::get_baked_length);
ClassDB::bind_method(D_METHOD("interpolate_baked", "offset", "cubic"), &Curve2D::interpolate_baked, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_baked_points"), &Curve2D::get_baked_points);
- ClassDB::bind_method(D_METHOD("tesselate", "max_stages", "tolerance_degrees"), &Curve2D::tesselate, DEFVAL(5), DEFVAL(4));
+ ClassDB::bind_method(D_METHOD("tessellate", "max_stages", "tolerance_degrees"), &Curve2D::tessellate, DEFVAL(5), DEFVAL(4));
ClassDB::bind_method(D_METHOD("_get_data"), &Curve2D::_get_data);
ClassDB::bind_method(D_METHOD("_set_data"), &Curve2D::_set_data);
@@ -1683,7 +1683,7 @@ void Curve3D::_set_data(const Dictionary &p_data) {
baked_cache_dirty = true;
}
-PoolVector3Array Curve3D::tesselate(int p_max_stages, float p_tolerance) const {
+PoolVector3Array Curve3D::tessellate(int p_max_stages, float p_tolerance) const {
PoolVector3Array tess;
@@ -1748,7 +1748,7 @@ void Curve3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("interpolate_baked", "offset", "cubic"), &Curve3D::interpolate_baked, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_baked_points"), &Curve3D::get_baked_points);
ClassDB::bind_method(D_METHOD("get_baked_tilts"), &Curve3D::get_baked_tilts);
- ClassDB::bind_method(D_METHOD("tesselate", "max_stages", "tolerance_degrees"), &Curve3D::tesselate, DEFVAL(5), DEFVAL(4));
+ ClassDB::bind_method(D_METHOD("tessellate", "max_stages", "tolerance_degrees"), &Curve3D::tessellate, DEFVAL(5), DEFVAL(4));
ClassDB::bind_method(D_METHOD("_get_data"), &Curve3D::_get_data);
ClassDB::bind_method(D_METHOD("_set_data"), &Curve3D::_set_data);
diff --git a/scene/resources/curve.h b/scene/resources/curve.h
index 83a4357bfb..2815c12c4b 100644
--- a/scene/resources/curve.h
+++ b/scene/resources/curve.h
@@ -249,7 +249,7 @@ public:
Vector2 interpolate_baked(float p_offset, bool p_cubic = false) const;
PoolVector2Array get_baked_points() const; //useful for going through
- PoolVector2Array tesselate(int p_max_stages = 5, float p_tolerance = 4) const; //useful for display
+ PoolVector2Array tessellate(int p_max_stages = 5, float p_tolerance = 4) const; //useful for display
Curve2D();
};
@@ -318,7 +318,7 @@ public:
PoolVector3Array get_baked_points() const; //useful for going through
PoolRealArray get_baked_tilts() const; //useful for going through
- PoolVector3Array tesselate(int p_max_stages = 5, float p_tolerance = 4) const; //useful for display
+ PoolVector3Array tessellate(int p_max_stages = 5, float p_tolerance = 4) const; //useful for display
Curve3D();
};
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 668a8ff66f..3e612c745f 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -510,20 +510,24 @@ void fill_default_theme(Ref<Theme> &t, const Ref<Font> &default_font, const Ref<
t->set_stylebox("slider", "HSlider", make_stylebox(hslider_bg_png, 4, 4, 4, 4));
t->set_stylebox("grabber_highlight", "HSlider", make_stylebox(hslider_grabber_hl_png, 6, 6, 6, 6));
+ t->set_stylebox("grabber_disabled", "HSlider", make_stylebox(hslider_grabber_disabled_png, 6, 6, 6, 6));
t->set_stylebox("focus", "HSlider", focus);
t->set_icon("grabber", "HSlider", make_icon(hslider_grabber_png));
t->set_icon("grabber_highlight", "HSlider", make_icon(hslider_grabber_hl_png));
+ t->set_icon("grabber_disabled", "HSlider", make_icon(hslider_grabber_disabled_png));
t->set_icon("tick", "HSlider", make_icon(hslider_tick_png));
// VSlider
t->set_stylebox("slider", "VSlider", make_stylebox(vslider_bg_png, 4, 4, 4, 4));
t->set_stylebox("grabber_highlight", "VSlider", make_stylebox(vslider_grabber_hl_png, 6, 6, 6, 6));
+ t->set_stylebox("grabber_disabled", "VSlider", make_stylebox(vslider_grabber_disabled_png, 6, 6, 6, 6));
t->set_stylebox("focus", "HSlider", focus);
t->set_icon("grabber", "VSlider", make_icon(vslider_grabber_png));
t->set_icon("grabber_highlight", "VSlider", make_icon(vslider_grabber_hl_png));
+ t->set_icon("grabber_disabled", "VSlider", make_icon(vslider_grabber_disabled_png));
t->set_icon("tick", "VSlider", make_icon(vslider_tick_png));
// SpinBox
@@ -757,11 +761,11 @@ void fill_default_theme(Ref<Theme> &t, const Ref<Font> &default_font, const Ref<
// colorPicker
- t->set_constant("value_height", "ColorPicker", 23 * scale);
- t->set_constant("value_width", "ColorPicker", 50 * scale);
- t->set_constant("color_width", "ColorPicker", 100 * scale);
- t->set_constant("label_width", "ColorPicker", 20 * scale);
- t->set_constant("hseparator", "ColorPicker", 4 * scale);
+ t->set_constant("margin", "ColorPicker", 4 * scale);
+ t->set_constant("sv_width", "ColorPicker", 256 * scale);
+ t->set_constant("sv_height", "ColorPicker", 256 * scale);
+ t->set_constant("h_width", "ColorPicker", 30 * scale);
+ t->set_constant("label_width", "ColorPicker", 10 * scale);
t->set_icon("screen_picker", "ColorPicker", make_icon(icon_color_pick_png));
t->set_icon("add_preset", "ColorPicker", make_icon(icon_add_png));
diff --git a/scene/resources/default_theme/hslider_grabber_disabled.png b/scene/resources/default_theme/hslider_grabber_disabled.png
new file mode 100644
index 0000000000..0d75182b8f
--- /dev/null
+++ b/scene/resources/default_theme/hslider_grabber_disabled.png
Binary files differ
diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h
index b9c401525a..70a8ad12cb 100644
--- a/scene/resources/default_theme/theme_data.h
+++ b/scene/resources/default_theme/theme_data.h
@@ -138,6 +138,10 @@ static const unsigned char hslider_grabber_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x1, 0x1d, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x85, 0xd1, 0x3f, 0x4b, 0xc3, 0x40, 0x18, 0xc7, 0xf1, 0xef, 0x25, 0xad, 0x89, 0xa9, 0x70, 0x83, 0x43, 0x5d, 0xc4, 0x21, 0x6e, 0x4a, 0x7, 0x47, 0xdf, 0x83, 0x53, 0x16, 0x17, 0xd7, 0x4e, 0xbe, 0x2, 0x5f, 0x85, 0x83, 0xa0, 0xb8, 0x38, 0xb8, 0x88, 0xd0, 0x51, 0x5d, 0x1c, 0x1c, 0x1c, 0x1c, 0x2a, 0xa2, 0xe8, 0x22, 0x2d, 0x82, 0x2d, 0x88, 0x54, 0xed, 0x3f, 0x1b, 0x9a, 0x78, 0x49, 0x1c, 0x9a, 0x54, 0x4f, 0x5, 0x6f, 0x3a, 0xee, 0xf9, 0xf0, 0x3c, 0x3f, 0x9e, 0x83, 0x7f, 0x8e, 0x18, 0xdf, 0x4c, 0x1c, 0x24, 0x5, 0x60, 0x40, 0x17, 0x9f, 0x48, 0x7, 0x26, 0xd3, 0xe5, 0x55, 0xd7, 0x93, 0x25, 0xe8, 0xde, 0xd4, 0x2b, 0xbb, 0x7, 0xbc, 0x8e, 0x88, 0x99, 0x82, 0xa9, 0xf2, 0xda, 0xe2, 0x86, 0x58, 0x78, 0xb7, 0x87, 0xf6, 0xc4, 0xdc, 0xcc, 0xd2, 0x6c, 0xfb, 0xf2, 0x8e, 0x10, 0xc0, 0x48, 0x81, 0x74, 0x3d, 0x55, 0xf4, 0x51, 0x28, 0x7c, 0x54, 0xd1, 0xf5, 0x90, 0xa3, 0x42, 0x6, 0xa, 0xb2, 0x14, 0x90, 0x0, 0x90, 0x10, 0x20, 0x4b, 0x14, 0x74, 0x20, 0x62, 0xf1, 0x3d, 0x7b, 0x24, 0xb2, 0x74, 0x19, 0x8, 0x83, 0x96, 0x39, 0x2e, 0xb, 0x82, 0x37, 0x94, 0xe, 0x6, 0xbd, 0xdb, 0xfc, 0x18, 0xe4, 0x49, 0x9e, 0xf0, 0x75, 0xd0, 0xbf, 0x3e, 0xb6, 0x22, 0x23, 0x7d, 0x9a, 0x4c, 0xce, 0xf6, 0xe8, 0xe9, 0x20, 0xb8, 0xaa, 0x6, 0xcd, 0x1c, 0x0, 0x39, 0x3e, 0x1e, 0x4f, 0xce, 0x7f, 0x76, 0x88, 0x1f, 0x1a, 0xcf, 0xa7, 0xe, 0x6, 0x6, 0xe, 0x8d, 0x23, 0xd5, 0x22, 0xd6, 0x41, 0x42, 0x77, 0x6b, 0x33, 0xaa, 0x59, 0x58, 0xc4, 0xf5, 0x9d, 0xed, 0x6c, 0xc0, 0xd7, 0x26, 0x21, 0xe, 0x7, 0x9d, 0xda, 0xf2, 0x8a, 0x1d, 0x1f, 0xae, 0xdf, 0x57, 0x19, 0xfe, 0x6, 0xa0, 0x9a, 0x2f, 0xf3, 0xed, 0xfe, 0xc5, 0x7e, 0x85, 0xce, 0x5f, 0xbf, 0x39, 0xca, 0x67, 0x21, 0x18, 0x66, 0x3b, 0x0, 0xf8, 0x4, 0x7e, 0x5c, 0x62, 0x33, 0x51, 0xf0, 0xbb, 0xff, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
+static const unsigned char hslider_grabber_disabled_png[] = {
+ 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe1, 0x7, 0xa, 0x13, 0x2f, 0x7, 0x5e, 0x49, 0xee, 0x14, 0x0, 0x0, 0x0, 0x1d, 0x69, 0x54, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x0, 0x0, 0x0, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x64, 0x2e, 0x65, 0x7, 0x0, 0x0, 0x0, 0xea, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x63, 0x60, 0x20, 0x1a, 0x30, 0x33, 0xf0, 0x32, 0xc8, 0x30, 0xa8, 0x3, 0xa1, 0xc, 0x90, 0xc5, 0x8c, 0x29, 0x2d, 0x66, 0x9c, 0xe7, 0x7a, 0xd0, 0xe7, 0xbd, 0xcf, 0x7b, 0xd7, 0x83, 0xc6, 0x79, 0xc, 0x62, 0xe8, 0x4a, 0x78, 0x8d, 0xf3, 0x3c, 0x5f, 0xb8, 0xff, 0x77, 0x1, 0x42, 0xf7, 0xff, 0x9e, 0x2f, 0x80, 0x4a, 0x78, 0x51, 0x15, 0xc8, 0xb8, 0x1e, 0x74, 0xff, 0xef, 0x4, 0x85, 0xee, 0xff, 0x5d, 0xf, 0x2, 0x2d, 0x42, 0x1, 0xea, 0x3e, 0xef, 0x5d, 0xe0, 0xa, 0x5c, 0xfe, 0xfb, 0xbc, 0x7, 0xba, 0x5, 0x5, 0x68, 0x78, 0x7f, 0x40, 0x56, 0xe0, 0xfd, 0x81, 0x41, 0x3, 0x55, 0x81, 0x92, 0xc7, 0x6d, 0x57, 0x24, 0x5, 0xee, 0xf7, 0x18, 0x54, 0x50, 0x15, 0x88, 0x3b, 0xae, 0xf7, 0x40, 0x72, 0x83, 0xfb, 0x51, 0x6, 0x29, 0x54, 0x5, 0x5c, 0x9a, 0xa9, 0xde, 0x7f, 0x9c, 0xc1, 0xd2, 0xce, 0xff, 0xbd, 0xff, 0xa9, 0xa7, 0x30, 0xf0, 0xa0, 0x85, 0x83, 0xa0, 0xa1, 0xc7, 0x3, 0x88, 0x25, 0xae, 0xff, 0x3d, 0x1f, 0x30, 0x69, 0x30, 0x30, 0xa1, 0x2a, 0x60, 0x64, 0x10, 0xb1, 0x99, 0xe3, 0x5, 0xd4, 0xed, 0xfc, 0xdf, 0xeb, 0xbf, 0xd5, 0x54, 0x6, 0x61, 0xcc, 0xa0, 0x66, 0x65, 0xd3, 0xf1, 0xb8, 0xed, 0xf6, 0xdf, 0xed, 0xbf, 0xe7, 0x1d, 0x36, 0x1d, 0x6, 0x56, 0x6c, 0xb1, 0xc1, 0x2d, 0xe3, 0xef, 0xf7, 0xc5, 0xef, 0xbb, 0x42, 0x28, 0xba, 0xfd, 0x48, 0xd6, 0x58, 0x16, 0xdb, 0xd6, 0x2, 0xe3, 0x81, 0x11, 0x57, 0x8c, 0xb2, 0x30, 0x70, 0x3, 0x75, 0xb3, 0x20, 0xb, 0x1, 0x0, 0x4, 0x5c, 0x63, 0x9b, 0x17, 0x86, 0x76, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
+};
+
static const unsigned char hslider_grabber_hl_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0xc6, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x48, 0x83, 0x83, 0x60, 0xaf, 0xb1, 0x65, 0xbb, 0xca, 0x61, 0xb3, 0xc2, 0x0, 0x0, 0x0, 0x63, 0xb7, 0xc8, 0x63, 0xb7, 0xc7, 0x0, 0x0, 0x0, 0x61, 0xb3, 0xbc, 0x60, 0xb1, 0xbc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5b, 0xa6, 0xa5, 0x63, 0xb4, 0xb6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0x69, 0x69, 0x5e, 0xb1, 0xcd, 0x5e, 0xb0, 0xcd, 0x36, 0x63, 0x63, 0x0, 0x0, 0x0, 0x17, 0x2a, 0x29, 0x60, 0xb2, 0xbd, 0x62, 0xb3, 0xbf, 0x3, 0x5, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55, 0x9b, 0x9a, 0x52, 0x96, 0x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0xf, 0xf, 0x62, 0xb4, 0xbd, 0x63, 0xb7, 0xbf, 0x0, 0x0, 0x0, 0x27, 0x48, 0x47, 0x68, 0xc0, 0xcf, 0x68, 0xc1, 0xcf, 0x2d, 0x52, 0x52, 0x51, 0x93, 0x92, 0x56, 0x9d, 0x9c, 0x0, 0x0, 0x0, 0x54, 0xa2, 0xc8, 0x4c, 0x94, 0xc2, 0x48, 0x8e, 0xc0, 0x47, 0x8c, 0xbf, 0x4b, 0x93, 0xc2, 0x4b, 0x92, 0xc2, 0x4f, 0x98, 0xc4, 0x4d, 0x96, 0xc3, 0x55, 0xa3, 0xc8, 0x53, 0x9f, 0xc7, 0x49, 0x8f, 0xc0, 0x4e, 0x97, 0xc4, 0x5a, 0xab, 0xcb, 0x5a, 0xac, 0xcc, 0x52, 0x9e, 0xc6, 0x51, 0x9d, 0xc6, 0xff, 0xff, 0xff, 0x6b, 0x1e, 0xb5, 0x61, 0x0, 0x0, 0x0, 0x31, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x3, 0xd, 0x1c, 0x27, 0x16, 0x6e, 0xc1, 0xef, 0xe8, 0x28, 0xf0, 0xf0, 0x22, 0xdb, 0xde, 0x24, 0x17, 0xaf, 0xc5, 0x1a, 0xa, 0x65, 0xfc, 0xfe, 0x64, 0xc, 0x31, 0xe0, 0xe0, 0x28, 0x2, 0x1, 0x14, 0x9c, 0x95, 0x13, 0x5, 0x2c, 0xdb, 0xdc, 0xb, 0x4f, 0xf4, 0xf7, 0x55, 0x73, 0x7d, 0x4, 0x28, 0xf1, 0xfd, 0xa1, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x41, 0x89, 0xde, 0x6c, 0x4e, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x4, 0x4e, 0x1d, 0x2, 0xaf, 0x0, 0x0, 0x0, 0x9e, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x6d, 0xcf, 0xd7, 0x12, 0x82, 0x30, 0x10, 0x5, 0x50, 0x48, 0x42, 0x12, 0xb0, 0x77, 0x8d, 0xd, 0xb, 0x28, 0x56, 0x12, 0x62, 0xd, 0x96, 0xff, 0xff, 0x2a, 0x61, 0xc, 0xe0, 0x83, 0xfb, 0xb4, 0xf7, 0xcc, 0xec, 0xcc, 0x5d, 0xc3, 0xf8, 0x37, 0x26, 0x80, 0x8, 0x41, 0x60, 0xe6, 0xd9, 0xc2, 0x84, 0x52, 0x82, 0xad, 0x4c, 0x0, 0xb6, 0xb9, 0x10, 0xdc, 0xc6, 0x40, 0x3, 0x24, 0x3c, 0x92, 0x32, 0xe2, 0x4, 0x6a, 0x40, 0x54, 0xc8, 0x64, 0x4, 0x45, 0x1a, 0x9c, 0xd2, 0x29, 0x85, 0x73, 0xd9, 0xd1, 0x50, 0xa9, 0x5e, 0x52, 0xb8, 0xd6, 0xea, 0x1a, 0x1a, 0xcd, 0x5b, 0xa, 0xf7, 0x56, 0x5b, 0x43, 0xa7, 0xdb, 0x53, 0x52, 0xaa, 0xfe, 0x80, 0x65, 0x3d, 0x86, 0xa3, 0x58, 0xca, 0x78, 0x3c, 0x99, 0x6a, 0x70, 0x67, 0xf3, 0x87, 0x52, 0xcf, 0xc5, 0x32, 0xaf, 0xee, 0xf9, 0xab, 0xd7, 0x7b, 0xed, 0x7b, 0xc5, 0x33, 0xc1, 0x66, 0xbb, 0xdb, 0xb3, 0x22, 0x27, 0x47, 0x87, 0xa3, 0xe5, 0xfe, 0xfe, 0x1b, 0x6, 0x2c, 0xfc, 0x6e, 0x1f, 0x93, 0x2a, 0x10, 0x62, 0x3, 0x21, 0x32, 0x75, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
@@ -434,6 +438,10 @@ static const unsigned char vslider_grabber_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xb7, 0xff, 0x88, 0x5, 0x1d, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe1, 0x1, 0x12, 0x1, 0x36, 0x8, 0x50, 0xb9, 0xa7, 0x53, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0xf6, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0xbd, 0x90, 0xb1, 0x4a, 0x42, 0x51, 0x0, 0x86, 0xbf, 0x73, 0x8e, 0x71, 0xe5, 0x9a, 0x5c, 0x41, 0xd0, 0x66, 0x6b, 0x33, 0x1c, 0x7c, 0x80, 0xa0, 0xa5, 0x17, 0x8, 0xa2, 0x2d, 0x84, 0xf0, 0x1, 0xa2, 0x25, 0xf1, 0x9, 0x9a, 0x1c, 0xda, 0x5b, 0xb2, 0x47, 0xa8, 0xa5, 0xc1, 0xa0, 0x51, 0x88, 0xa2, 0x29, 0xa, 0xc1, 0x84, 0x8, 0x43, 0xf4, 0x96, 0x17, 0xcf, 0xed, 0xde, 0x73, 0x9c, 0xcc, 0x5c, 0xda, 0xea, 0x9f, 0x3f, 0xfe, 0x9f, 0xef, 0x87, 0x3f, 0x8f, 0x0, 0x40, 0xe1, 0xe2, 0x91, 0x42, 0x10, 0x32, 0xe6, 0x3, 0x8d, 0xc1, 0xce, 0x1, 0x45, 0xb6, 0xba, 0xbb, 0xba, 0xed, 0x95, 0x8c, 0xd0, 0x7d, 0xff, 0xe1, 0xee, 0xe2, 0xb6, 0xdd, 0x79, 0x61, 0xc4, 0xd7, 0xc, 0x48, 0x57, 0x2b, 0xeb, 0xb5, 0x28, 0xaf, 0x1, 0xc5, 0x12, 0x4e, 0xac, 0x7b, 0x6f, 0x57, 0x27, 0x8d, 0xcf, 0xe, 0x1, 0x56, 0x1, 0xb9, 0x9d, 0xba, 0x28, 0x6, 0x18, 0xc, 0x31, 0x21, 0x5a, 0xda, 0x4c, 0xb6, 0xbc, 0xb9, 0x35, 0x7c, 0xea, 0xbd, 0x13, 0x4a, 0x20, 0xe5, 0x95, 0xf4, 0x6c, 0x12, 0x30, 0x84, 0xf8, 0x44, 0x6b, 0xfb, 0xcd, 0x83, 0x3d, 0x1c, 0xf9, 0x8b, 0x80, 0x4a, 0xba, 0x88, 0x4, 0x30, 0x1e, 0xdd, 0x3b, 0x1b, 0xf1, 0x77, 0x87, 0x24, 0x81, 0x8b, 0x79, 0x3e, 0x3b, 0x6a, 0x5d, 0x33, 0x51, 0x80, 0x2d, 0x38, 0x2b, 0x65, 0xb5, 0x6c, 0x91, 0x28, 0x92, 0xa4, 0xad, 0xec, 0x76, 0xcf, 0x8f, 0xf, 0x1f, 0xdb, 0xc, 0x31, 0xb, 0x9a, 0xb1, 0xd0, 0x3, 0xfb, 0xda, 0x3a, 0xbd, 0xbc, 0x89, 0xfa, 0xf8, 0x73, 0xcd, 0x9f, 0x47, 0x45, 0x4, 0xf8, 0x4, 0x18, 0xfe, 0x2f, 0x53, 0x8, 0x62, 0x5c, 0xcf, 0x1f, 0x5f, 0xcb, 0x2c, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
+static const unsigned char vslider_grabber_disabled_png[] = {
+ 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe1, 0x7, 0xa, 0x13, 0x2e, 0x39, 0x86, 0x33, 0xc2, 0xfe, 0x0, 0x0, 0x0, 0x1d, 0x69, 0x54, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x0, 0x0, 0x0, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x64, 0x2e, 0x65, 0x7, 0x0, 0x0, 0x0, 0xb7, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x63, 0x60, 0xa0, 0x13, 0x60, 0x66, 0xe0, 0x65, 0x90, 0x61, 0x50, 0x67, 0xd0, 0x60, 0x50, 0x62, 0x10, 0x67, 0xe0, 0x2, 0xf2, 0x19, 0x51, 0xa5, 0xc5, 0x8c, 0xf3, 0x5c, 0xf, 0xfa, 0xbc, 0xf7, 0xfe, 0xe0, 0x71, 0xdb, 0x71, 0xbd, 0x66, 0xaa, 0xa0, 0x21, 0x83, 0x8, 0x3, 0x2b, 0x42, 0x1, 0xaf, 0x71, 0x9e, 0xe7, 0xb, 0xf7, 0xff, 0x2e, 0x40, 0xe8, 0xfa, 0xdf, 0xe3, 0xbf, 0xf7, 0x1f, 0x8f, 0x7, 0x36, 0x73, 0xd8, 0x74, 0x18, 0xb8, 0x61, 0xe6, 0xc8, 0xb8, 0x1e, 0x74, 0xff, 0xef, 0x4, 0x87, 0xce, 0x40, 0x65, 0x5e, 0xff, 0x3d, 0x6e, 0xcb, 0xf8, 0x3, 0xcd, 0x61, 0x1, 0x29, 0x50, 0xf7, 0x79, 0xef, 0x82, 0xa4, 0x0, 0xa2, 0xc8, 0xed, 0xbf, 0xdf, 0x17, 0xcb, 0x62, 0xa0, 0x29, 0x78, 0x14, 0x7c, 0xb7, 0xad, 0x65, 0xe0, 0xc1, 0x69, 0x85, 0xe7, 0x1d, 0x85, 0x50, 0x6, 0x31, 0x88, 0x15, 0x48, 0x8e, 0x74, 0xf9, 0xef, 0xfe, 0xdf, 0xfb, 0x9f, 0xe7, 0x3, 0xab, 0xa9, 0x40, 0x47, 0xf2, 0xc0, 0x1c, 0x89, 0xe4, 0x4d, 0xf7, 0x7b, 0xee, 0x47, 0xd5, 0x53, 0x98, 0x34, 0x18, 0x84, 0x91, 0xbd, 0x89, 0x1c, 0x50, 0x2a, 0xc, 0x52, 0x40, 0x9d, 0x4c, 0xc, 0xf4, 0x4, 0x0, 0xf1, 0x9, 0x63, 0x9b, 0x3e, 0x2a, 0x19, 0x52, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
+};
+
static const unsigned char vslider_grabber_hl_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0xc3, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x17, 0x2a, 0x29, 0x3a, 0x69, 0x69, 0x5b, 0xa6, 0xa5, 0x61, 0xb3, 0xbc, 0x63, 0xb7, 0xc8, 0x65, 0xbb, 0xca, 0x60, 0xaf, 0xb1, 0x48, 0x83, 0x83, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0xf, 0xf, 0x55, 0x9b, 0x9a, 0x60, 0xb2, 0xbd, 0x5e, 0xb1, 0xcd, 0x61, 0xb3, 0xc2, 0x0, 0x0, 0x0, 0x27, 0x48, 0x47, 0x62, 0xb4, 0xbd, 0x51, 0x93, 0x92, 0x68, 0xc0, 0xcf, 0x0, 0x0, 0x0, 0x56, 0x9d, 0x9c, 0x68, 0xc1, 0xcf, 0x2d, 0x52, 0x52, 0x63, 0xb7, 0xbf, 0x52, 0x96, 0x95, 0x62, 0xb3, 0xbf, 0x5e, 0xb0, 0xcd, 0x0, 0x0, 0x0, 0x3, 0x5, 0x5, 0x36, 0x63, 0x63, 0x63, 0xb4, 0xb6, 0x60, 0xb1, 0xbc, 0x63, 0xb7, 0xc7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55, 0xa3, 0xc8, 0x4f, 0x98, 0xc4, 0x4b, 0x93, 0xc2, 0x4c, 0x94, 0xc2, 0x54, 0xa2, 0xc8, 0x5a, 0xab, 0xcb, 0x4e, 0x97, 0xc4, 0x49, 0x8f, 0xc0, 0x47, 0x8c, 0xbf, 0x48, 0x8e, 0xc0, 0x52, 0x9e, 0xc6, 0x51, 0x9d, 0xc6, 0x5a, 0xac, 0xcc, 0x53, 0x9f, 0xc7, 0x4d, 0x96, 0xc3, 0x4b, 0x92, 0xc2, 0xff, 0xff, 0xff, 0x76, 0xbd, 0x27, 0x7a, 0x0, 0x0, 0x0, 0x1, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x40, 0xe6, 0xd8, 0x66, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x0, 0x88, 0x5, 0x1d, 0x48, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe1, 0x1, 0x12, 0x1, 0x36, 0x11, 0x34, 0xd2, 0xf, 0x93, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x48, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x63, 0x60, 0xa0, 0x12, 0x10, 0x14, 0xe0, 0xe7, 0xe3, 0x45, 0xe2, 0x4b, 0x9a, 0x18, 0x1b, 0x19, 0x1a, 0x48, 0x88, 0x8b, 0xc1, 0xe4, 0x4d, 0x2c, 0x2d, 0x80, 0xc0, 0xdc, 0xcc, 0x54, 0x6, 0x22, 0x20, 0x60, 0x6c, 0x1, 0x1, 0xe6, 0x56, 0x72, 0x68, 0x2, 0xd6, 0x8a, 0xa8, 0x5a, 0x6c, 0x94, 0x11, 0x86, 0xda, 0xdb, 0xd9, 0xaa, 0xa9, 0xaa, 0x20, 0x59, 0xab, 0xa3, 0xad, 0xc5, 0x40, 0x3d, 0x0, 0x0, 0xbf, 0x8e, 0xc, 0xed, 0xed, 0xc7, 0x67, 0x72, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
diff --git a/scene/resources/default_theme/vslider_grabber_disabled.png b/scene/resources/default_theme/vslider_grabber_disabled.png
new file mode 100644
index 0000000000..c830359f45
--- /dev/null
+++ b/scene/resources/default_theme/vslider_grabber_disabled.png
Binary files differ
diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp
index d2848076a0..2fdc4c9e24 100644
--- a/scene/resources/dynamic_font.cpp
+++ b/scene/resources/dynamic_font.cpp
@@ -338,7 +338,7 @@ float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharT
cpos.y += ch->v_align;
ERR_FAIL_COND_V(ch->texture_idx < -1 || ch->texture_idx >= fb->textures.size(), 0);
if (ch->texture_idx != -1)
- VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, ch->rect.size), fb->textures[ch->texture_idx].texture->get_rid(), ch->rect, p_modulate);
+ VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, ch->rect.size), fb->textures[ch->texture_idx].texture->get_rid(), ch->rect, p_modulate, false, RID(), false);
advance = ch->advance;
used_fallback = true;
break;
@@ -360,7 +360,7 @@ float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharT
cpos.y += c->v_align;
ERR_FAIL_COND_V(c->texture_idx < -1 || c->texture_idx >= textures.size(), 0);
if (c->texture_idx != -1)
- VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, c->rect.size), textures[c->texture_idx].texture->get_rid(), c->rect, p_modulate);
+ VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, c->rect.size), textures[c->texture_idx].texture->get_rid(), c->rect, p_modulate, false, RID(), false);
advance = c->advance;
//textures[c->texture_idx].texture->draw(p_canvas_item,Vector2());
}
diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp
index 24e3977de8..accced404b 100644
--- a/scene/resources/environment.cpp
+++ b/scene/resources/environment.cpp
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "environment.h"
-#include "global_config.h"
+#include "project_settings.h"
#include "servers/visual_server.h"
#include "texture.h"
@@ -167,6 +167,7 @@ void Environment::set_tonemap_auto_exposure(bool p_enabled) {
tonemap_auto_exposure = p_enabled;
VS::get_singleton()->environment_set_tonemap(environment, VS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey);
+ _change_notify();
}
bool Environment::get_tonemap_auto_exposure() const {
@@ -471,7 +472,7 @@ bool Environment::is_ssao_blur_enabled() const {
void Environment::set_glow_enabled(bool p_enabled) {
glow_enabled = p_enabled;
- VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_treshold, glow_hdr_bleed_treshold, glow_bicubic_upscale);
+ VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_bicubic_upscale);
_change_notify();
}
@@ -489,7 +490,7 @@ void Environment::set_glow_level(int p_level, bool p_enabled) {
else
glow_levels &= ~(1 << p_level);
- VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_treshold, glow_hdr_bleed_treshold, glow_bicubic_upscale);
+ VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_bicubic_upscale);
}
bool Environment::is_glow_level_enabled(int p_level) const {
@@ -502,7 +503,7 @@ void Environment::set_glow_intensity(float p_intensity) {
glow_intensity = p_intensity;
- VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_treshold, glow_hdr_bleed_treshold, glow_bicubic_upscale);
+ VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_bicubic_upscale);
}
float Environment::get_glow_intensity() const {
@@ -512,18 +513,18 @@ float Environment::get_glow_intensity() const {
void Environment::set_glow_strength(float p_strength) {
glow_strength = p_strength;
- VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_treshold, glow_hdr_bleed_treshold, glow_bicubic_upscale);
+ VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_bicubic_upscale);
}
float Environment::get_glow_strength() const {
return glow_strength;
}
-void Environment::set_glow_bloom(float p_treshold) {
+void Environment::set_glow_bloom(float p_threshold) {
- glow_bloom = p_treshold;
+ glow_bloom = p_threshold;
- VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_treshold, glow_hdr_bleed_treshold, glow_bicubic_upscale);
+ VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_bicubic_upscale);
}
float Environment::get_glow_bloom() const {
@@ -534,29 +535,29 @@ void Environment::set_glow_blend_mode(GlowBlendMode p_mode) {
glow_blend_mode = p_mode;
- VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_treshold, glow_hdr_bleed_treshold, glow_bicubic_upscale);
+ VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_bicubic_upscale);
}
Environment::GlowBlendMode Environment::get_glow_blend_mode() const {
return glow_blend_mode;
}
-void Environment::set_glow_hdr_bleed_treshold(float p_treshold) {
+void Environment::set_glow_hdr_bleed_threshold(float p_threshold) {
- glow_hdr_bleed_treshold = p_treshold;
+ glow_hdr_bleed_threshold = p_threshold;
- VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_treshold, glow_hdr_bleed_treshold, glow_bicubic_upscale);
+ VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_bicubic_upscale);
}
-float Environment::get_glow_hdr_bleed_treshold() const {
+float Environment::get_glow_hdr_bleed_threshold() const {
- return glow_hdr_bleed_treshold;
+ return glow_hdr_bleed_threshold;
}
void Environment::set_glow_hdr_bleed_scale(float p_scale) {
glow_hdr_bleed_scale = p_scale;
- VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_treshold, glow_hdr_bleed_treshold, glow_bicubic_upscale);
+ VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_bicubic_upscale);
}
float Environment::get_glow_hdr_bleed_scale() const {
@@ -566,7 +567,7 @@ float Environment::get_glow_hdr_bleed_scale() const {
void Environment::set_glow_bicubic_upscale(bool p_enable) {
glow_bicubic_upscale = p_enable;
- VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_treshold, glow_hdr_bleed_treshold, glow_bicubic_upscale);
+ VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_bicubic_upscale);
}
bool Environment::is_glow_bicubic_upscale_enabled() const {
@@ -818,7 +819,7 @@ float Environment::get_fog_height_curve() const {
void Environment::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_background", "mode"), &Environment::set_background);
- ClassDB::bind_method(D_METHOD("set_sky", "sky:CubeMap"), &Environment::set_sky);
+ ClassDB::bind_method(D_METHOD("set_sky", "sky:Sky"), &Environment::set_sky);
ClassDB::bind_method(D_METHOD("set_sky_scale", "scale"), &Environment::set_sky_scale);
ClassDB::bind_method(D_METHOD("set_bg_color", "color"), &Environment::set_bg_color);
ClassDB::bind_method(D_METHOD("set_bg_energy", "energy"), &Environment::set_bg_energy);
@@ -1064,8 +1065,8 @@ void Environment::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_glow_blend_mode", "mode"), &Environment::set_glow_blend_mode);
ClassDB::bind_method(D_METHOD("get_glow_blend_mode"), &Environment::get_glow_blend_mode);
- ClassDB::bind_method(D_METHOD("set_glow_hdr_bleed_treshold", "treshold"), &Environment::set_glow_hdr_bleed_treshold);
- ClassDB::bind_method(D_METHOD("get_glow_hdr_bleed_treshold"), &Environment::get_glow_hdr_bleed_treshold);
+ ClassDB::bind_method(D_METHOD("set_glow_hdr_bleed_threshold", "threshold"), &Environment::set_glow_hdr_bleed_threshold);
+ ClassDB::bind_method(D_METHOD("get_glow_hdr_bleed_threshold"), &Environment::get_glow_hdr_bleed_threshold);
ClassDB::bind_method(D_METHOD("set_glow_hdr_bleed_scale", "scale"), &Environment::set_glow_hdr_bleed_scale);
ClassDB::bind_method(D_METHOD("get_glow_hdr_bleed_scale"), &Environment::get_glow_hdr_bleed_scale);
@@ -1087,7 +1088,7 @@ void Environment::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_strength", PROPERTY_HINT_RANGE, "0.0,2.0,0.01"), "set_glow_strength", "get_glow_strength");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_bloom", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_glow_bloom", "get_glow_bloom");
ADD_PROPERTY(PropertyInfo(Variant::INT, "glow_blend_mode", PROPERTY_HINT_ENUM, "Additive,Screen,Softlight,Replace"), "set_glow_blend_mode", "get_glow_blend_mode");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_hdr_treshold", PROPERTY_HINT_RANGE, "0.0,4.0,0.01"), "set_glow_hdr_bleed_treshold", "get_glow_hdr_bleed_treshold");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_hdr_threshold", PROPERTY_HINT_RANGE, "0.0,4.0,0.01"), "set_glow_hdr_bleed_threshold", "get_glow_hdr_bleed_threshold");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_hdr_scale", PROPERTY_HINT_RANGE, "0.0,4.0,0.01"), "set_glow_hdr_bleed_scale", "get_glow_hdr_bleed_scale");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "glow_bicubic_upscale"), "set_glow_bicubic_upscale", "is_glow_bicubic_upscale_enabled");
@@ -1103,8 +1104,8 @@ void Environment::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_adjustment_saturation", "saturation"), &Environment::set_adjustment_saturation);
ClassDB::bind_method(D_METHOD("get_adjustment_saturation"), &Environment::get_adjustment_saturation);
- ClassDB::bind_method(D_METHOD("set_adjustment_color_correction", "color_correction"), &Environment::set_adjustment_color_correction);
- ClassDB::bind_method(D_METHOD("get_adjustment_color_correction"), &Environment::get_adjustment_color_correction);
+ ClassDB::bind_method(D_METHOD("set_adjustment_color_correction", "color_correction:Texture"), &Environment::set_adjustment_color_correction);
+ ClassDB::bind_method(D_METHOD("get_adjustment_color_correction:Texture"), &Environment::get_adjustment_color_correction);
ADD_GROUP("Adjustments", "adjustment_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "adjustment_enabled"), "set_adjustment_enable", "is_adjustment_enabled");
@@ -1113,8 +1114,6 @@ void Environment::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::REAL, "adjustment_saturation", PROPERTY_HINT_RANGE, "0.01,8,0.01"), "set_adjustment_saturation", "get_adjustment_saturation");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "adjustment_color_correction", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_adjustment_color_correction", "get_adjustment_color_correction");
- GLOBAL_DEF("rendering/sky/irradiance_cube_resolution", 256);
-
BIND_CONSTANT(BG_KEEP);
BIND_CONSTANT(BG_CLEAR_COLOR);
BIND_CONSTANT(BG_COLOR);
@@ -1185,7 +1184,7 @@ Environment::Environment() {
glow_strength = 1.0;
glow_bloom = 0.0;
glow_blend_mode = GLOW_BLEND_MODE_SOFTLIGHT;
- glow_hdr_bleed_treshold = 1.0;
+ glow_hdr_bleed_threshold = 1.0;
glow_hdr_bleed_scale = 2.0;
glow_bicubic_upscale = false;
diff --git a/scene/resources/environment.h b/scene/resources/environment.h
index 7eda8506b5..a7c0e2a03d 100644
--- a/scene/resources/environment.h
+++ b/scene/resources/environment.h
@@ -121,7 +121,7 @@ private:
float glow_strength;
float glow_bloom;
GlowBlendMode glow_blend_mode;
- float glow_hdr_bleed_treshold;
+ float glow_hdr_bleed_threshold;
float glow_hdr_bleed_scale;
bool glow_bicubic_upscale;
@@ -275,14 +275,14 @@ public:
void set_glow_strength(float p_strength);
float get_glow_strength() const;
- void set_glow_bloom(float p_treshold);
+ void set_glow_bloom(float p_threshold);
float get_glow_bloom() const;
void set_glow_blend_mode(GlowBlendMode p_mode);
GlowBlendMode get_glow_blend_mode() const;
- void set_glow_hdr_bleed_treshold(float p_treshold);
- float get_glow_hdr_bleed_treshold() const;
+ void set_glow_hdr_bleed_threshold(float p_threshold);
+ float get_glow_hdr_bleed_threshold() const;
void set_glow_hdr_bleed_scale(float p_scale);
float get_glow_hdr_bleed_scale() const;
diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp
index 225a42f651..a6a70d775f 100644
--- a/scene/resources/font.cpp
+++ b/scene/resources/font.cpp
@@ -506,7 +506,7 @@ float BitmapFont::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_c
cpos.y += c->v_align;
ERR_FAIL_COND_V(c->texture_idx < -1 || c->texture_idx >= textures.size(), 0);
if (c->texture_idx != -1)
- VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, c->rect.size), textures[c->texture_idx]->get_rid(), c->rect, p_modulate);
+ VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, c->rect.size), textures[c->texture_idx]->get_rid(), c->rect, p_modulate, false, RID(), false);
return get_char_size(p_char, p_next).width;
}
@@ -570,8 +570,8 @@ void BitmapFont::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_textures"), &BitmapFont::_set_textures);
ClassDB::bind_method(D_METHOD("_get_textures"), &BitmapFont::_get_textures);
- ClassDB::bind_method(D_METHOD("set_fallback", "fallback"), &BitmapFont::set_fallback);
- ClassDB::bind_method(D_METHOD("get_fallback"), &BitmapFont::get_fallback);
+ ClassDB::bind_method(D_METHOD("set_fallback", "fallback:BitmapFont"), &BitmapFont::set_fallback);
+ ClassDB::bind_method(D_METHOD("get_fallback:BitmapFont"), &BitmapFont::get_fallback);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "textures", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_textures", "_get_textures");
ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "chars", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_chars", "_get_chars");
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 3934467855..24ec39afe3 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -30,11 +30,36 @@
#include "material.h"
#include "scene/scene_string_names.h"
+void Material::set_next_pass(const Ref<Material> &p_pass) {
+
+ if (next_pass == p_pass)
+ return;
+
+ next_pass = p_pass;
+ RID next_pass_rid;
+ if (next_pass.is_valid())
+ next_pass_rid = next_pass->get_rid();
+ VS::get_singleton()->material_set_next_pass(material, next_pass_rid);
+}
+
+Ref<Material> Material::get_next_pass() const {
+
+ return next_pass;
+}
+
RID Material::get_rid() const {
return material;
}
+void Material::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_next_pass", "next_pass:Material"), &Material::set_next_pass);
+ ClassDB::bind_method(D_METHOD("get_next_pass:Material"), &Material::get_next_pass);
+
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "next_pass", PROPERTY_HINT_RESOURCE_TYPE, "Material"), "set_next_pass", "get_next_pass");
+}
+
Material::Material() {
material = VisualServer::get_singleton()->material_create();
@@ -138,7 +163,7 @@ void ShaderMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_shader", "shader:Shader"), &ShaderMaterial::set_shader);
ClassDB::bind_method(D_METHOD("get_shader:Shader"), &ShaderMaterial::get_shader);
ClassDB::bind_method(D_METHOD("set_shader_param", "param", "value"), &ShaderMaterial::set_shader_param);
- ClassDB::bind_method(D_METHOD("get_shader_param", "param"), &ShaderMaterial::get_shader_param);
+ ClassDB::bind_method(D_METHOD("get_shader_param:Variant", "param"), &ShaderMaterial::get_shader_param);
}
void ShaderMaterial::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const {
@@ -198,6 +223,8 @@ void SpatialMaterial::init_shaders() {
shader_names->uv1_offset = "uv1_offset";
shader_names->uv2_scale = "uv2_scale";
shader_names->uv2_offset = "uv2_offset";
+ shader_names->uv1_blend_sharpness = "uv1_blend_sharpness";
+ shader_names->uv2_blend_sharpness = "uv2_blend_sharpness";
shader_names->particle_h_frames = "particle_h_frames";
shader_names->particle_v_frames = "particle_v_frames";
@@ -205,6 +232,8 @@ void SpatialMaterial::init_shaders() {
shader_names->depth_min_layers = "depth_min_layers";
shader_names->depth_max_layers = "depth_max_layers";
+ shader_names->grow = "grow";
+
shader_names->texture_names[TEXTURE_ALBEDO] = "texture_albedo";
shader_names->texture_names[TEXTURE_METALLIC] = "texture_metallic";
shader_names->texture_names[TEXTURE_ROUGHNESS] = "texture_roughness";
@@ -289,6 +318,14 @@ void SpatialMaterial::_update_shader() {
case DIFFUSE_HALF_LAMBERT: code += ",diffuse_half_lambert"; break;
case DIFFUSE_OREN_NAYAR: code += ",diffuse_oren_nayar"; break;
case DIFFUSE_BURLEY: code += ",diffuse_burley"; break;
+ case DIFFUSE_TOON: code += ",diffuse_toon"; break;
+ }
+ switch (specular_mode) {
+ case SPECULAR_SCHLICK_GGX: code += ",specular_schlick_ggx"; break;
+ case SPECULAR_BLINN: code += ",specular_blinn"; break;
+ case SPECULAR_PHONG: code += ",specular_phong"; break;
+ case SPECULAR_TOON: code += ",specular_toon"; break;
+ case SPECULAR_DISABLED: code += ",specular_disabled"; break;
}
if (flags[FLAG_UNSHADED]) {
@@ -297,22 +334,27 @@ void SpatialMaterial::_update_shader() {
if (flags[FLAG_ONTOP]) {
code += ",ontop";
}
+ if (flags[FLAG_USE_VERTEX_LIGHTING]) {
+ code += ",vertex_lighting";
+ }
+ if (flags[FLAG_UV1_USE_TRIPLANAR] || flags[FLAG_UV2_USE_TRIPLANAR]) {
+ code += ",world_vertex_coords";
+ }
code += ";\n";
code += "uniform vec4 albedo : hint_color;\n";
code += "uniform sampler2D texture_albedo : hint_albedo;\n";
code += "uniform float specular;\n";
code += "uniform float metallic;\n";
+ if (grow_enabled) {
+ code += "uniform float grow;\n";
+ }
code += "uniform float roughness : hint_range(0,1);\n";
code += "uniform float point_size : hint_range(0,128);\n";
code += "uniform sampler2D texture_metallic : hint_white;\n";
code += "uniform sampler2D texture_roughness : hint_white;\n";
- code += "uniform vec2 uv1_scale;\n";
- code += "uniform vec2 uv1_offset;\n";
- code += "uniform vec2 uv2_scale;\n";
- code += "uniform vec2 uv2_offset;\n";
if (billboard_mode == BILLBOARD_PARTICLES) {
code += "uniform int particles_anim_h_frames;\n";
code += "uniform int particles_anim_v_frames;\n";
@@ -371,6 +413,26 @@ void SpatialMaterial::_update_shader() {
code += "uniform int depth_min_layers;\n";
code += "uniform int depth_max_layers;\n";
}
+ if (flags[FLAG_UV1_USE_TRIPLANAR]) {
+ code += "varying vec3 uv1_world_pos;\n";
+ }
+ if (flags[FLAG_UV2_USE_TRIPLANAR]) {
+ code += "varying vec3 uv2_world_pos;\n";
+ }
+ if (flags[FLAG_UV1_USE_TRIPLANAR]) {
+ code += "uniform float uv1_blend_sharpness;\n";
+ code += "varying vec3 uv1_power_normal;\n";
+ }
+
+ if (flags[FLAG_UV2_USE_TRIPLANAR]) {
+ code += "uniform float uv2_blend_sharpness;\n";
+ code += "varying vec3 uv2_power_normal;\n";
+ }
+
+ code += "uniform vec3 uv1_scale;\n";
+ code += "uniform vec3 uv1_offset;\n";
+ code += "uniform vec3 uv2_scale;\n";
+ code += "uniform vec3 uv2_offset;\n";
code += "\n\n";
@@ -384,7 +446,15 @@ void SpatialMaterial::_update_shader() {
code += "\tPOINT_SIZE=point_size;\n";
}
- code += "\tUV=UV*uv1_scale+uv1_offset;\n";
+
+ if (flags[FLAG_USE_VERTEX_LIGHTING]) {
+
+ code += "\tROUGHNESS=roughness;\n";
+ }
+
+ if (!flags[FLAG_UV1_USE_TRIPLANAR]) {
+ code += "\tUV=UV*uv1_scale.xy+uv1_offset.xy;\n";
+ }
switch (billboard_mode) {
case BILLBOARD_DISABLED: {
@@ -414,7 +484,6 @@ void SpatialMaterial::_update_shader() {
//code += "\tUV+= UV * vec2(float(particle_frame % particles_anim_h_frames),float(particle_frame / particles_anim_v_frames));\n";
//handle rotation
// code += "\tmat4 rotation = mat4("
-
} break;
}
@@ -437,22 +506,67 @@ void SpatialMaterial::_update_shader() {
code += "\t}\n";
}
- if (detail_uv == DETAIL_UV_2) {
+ if (detail_uv == DETAIL_UV_2 && !flags[FLAG_UV2_USE_TRIPLANAR]) {
code += "\tUV2=UV2*uv2_scale+uv2_offset;\n";
}
+ if (flags[FLAG_UV1_USE_TRIPLANAR] || flags[FLAG_UV2_USE_TRIPLANAR]) {
+ //generate tangent and binormal in world space
+ code += "\tTANGENT = vec3(0.0,0.0,-1.0) * abs(NORMAL.x);\n";
+ code += "\tTANGENT+= vec3(1.0,0.0,0.0) * abs(NORMAL.y);\n";
+ code += "\tTANGENT+= vec3(1.0,0.0,0.0) * abs(NORMAL.z);\n";
+ code += "\tTANGENT = normalize(TANGENT);\n";
+
+ code += "\tBINORMAL = vec3(0.0,1.0,0.0) * abs(NORMAL.x);\n";
+ code += "\tBINORMAL+= vec3(0.0,0.0,-1.0) * abs(NORMAL.y);\n";
+ code += "\tBINORMAL+= vec3(0.0,1.0,0.0) * abs(NORMAL.z);\n";
+ code += "\tBINORMAL = normalize(BINORMAL);\n";
+ }
+
+ if (flags[FLAG_UV1_USE_TRIPLANAR]) {
+
+ code += "\tuv1_power_normal=pow(abs(NORMAL),vec3(uv1_blend_sharpness));\n";
+ code += "\tuv1_power_normal/=dot(uv1_power_normal,vec3(1.0));\n";
+ code += "\tuv1_world_pos = VERTEX * uv1_scale + uv1_offset;\n";
+ code += "\tuv1_world_pos *= vec3(1.0,-1.0, 1.0);\n";
+ }
+
+ if (flags[FLAG_UV2_USE_TRIPLANAR]) {
+
+ code += "\tuv2_power_normal=pow(abs(NORMAL), vec3(uv2_blend_sharpness));\n";
+ code += "\tuv2_power_normal/=dot(uv2_power_normal,vec3(1.0));\n";
+ code += "\tuv2_world_pos = VERTEX * uv2_scale + uv2_offset;\n";
+ code += "\tuv2_world_pos *= vec3(1.0,-1.0, 1.0);\n";
+ }
+
+ if (grow_enabled) {
+ code += "\tVERTEX+=NORMAL*grow;\n";
+ }
code += "}\n";
code += "\n\n";
+ if (flags[FLAG_UV1_USE_TRIPLANAR] || flags[FLAG_UV2_USE_TRIPLANAR]) {
+ code += "vec4 triplanar_texture(sampler2D p_sampler,vec3 p_weights,vec3 p_world_pos) {\n";
+ code += "\tvec4 samp=vec4(0.0);\n";
+ code += "\tsamp+= texture(p_sampler,p_world_pos.xy) * p_weights.z;\n";
+ code += "\tsamp+= texture(p_sampler,p_world_pos.xz) * p_weights.y;\n";
+ code += "\tsamp+= texture(p_sampler,p_world_pos.zy * vec2(-1.0,1.0)) * p_weights.x;\n";
+ code += "\treturn samp;\n";
+ code += "}\n";
+ }
+ code += "\n\n";
code += "void fragment() {\n";
- code += "\tvec2 base_uv = UV;\n";
- if (features[FEATURE_DETAIL] && detail_uv == DETAIL_UV_2) {
+ if (!flags[FLAG_UV1_USE_TRIPLANAR]) {
+ code += "\tvec2 base_uv = UV;\n";
+ }
+
+ if ((features[FEATURE_DETAIL] && detail_uv == DETAIL_UV_2) || (features[FEATURE_AMBIENT_OCCLUSION] && flags[FLAG_AO_ON_UV2])) {
code += "\tvec2 base_uv2 = UV2;\n";
}
- if (features[FEATURE_DEPTH_MAPPING]) {
+ if (features[FEATURE_DEPTH_MAPPING] && !flags[FLAG_UV1_USE_TRIPLANAR]) { //depthmap not supported with triplanar
code += "\t{\n";
- code += "\t\tvec3 view_dir = normalize(normalize(-VERTEX)*mat3(TANGENT,BINORMAL,NORMAL));\n";
+ code += "\t\tvec3 view_dir = normalize(normalize(-VERTEX)*mat3(TANGENT,-BINORMAL,NORMAL));\n"; //binormal is negative due to mikktpsace
if (deep_parallax) {
code += "\t\tfloat num_layers = mix(float(depth_max_layers),float(depth_min_layers), abs(dot(vec3(0.0, 0.0, 1.0), view_dir)));\n";
@@ -490,7 +604,11 @@ void SpatialMaterial::_update_shader() {
if (flags[FLAG_USE_POINT_SIZE]) {
code += "\tvec4 albedo_tex = texture(texture_albedo,POINT_COORD);\n";
} else {
- code += "\tvec4 albedo_tex = texture(texture_albedo,base_uv);\n";
+ if (flags[FLAG_UV1_USE_TRIPLANAR]) {
+ code += "\tvec4 albedo_tex = triplanar_texture(texture_albedo,uv1_power_normal,uv1_world_pos);\n";
+ } else {
+ code += "\tvec4 albedo_tex = texture(texture_albedo,base_uv);\n";
+ }
}
if (flags[FLAG_ALBEDO_FROM_VERTEX_COLOR]) {
@@ -498,22 +616,39 @@ void SpatialMaterial::_update_shader() {
}
code += "\tALBEDO = albedo.rgb * albedo_tex.rgb;\n";
- code += "\tfloat metallic_tex = texture(texture_metallic,base_uv).r;\n";
+ if (flags[FLAG_UV1_USE_TRIPLANAR]) {
+ code += "\tfloat metallic_tex = triplanar_texture(texture_metallic,uv1_power_normal,uv1_world_pos).r;\n";
+ } else {
+ code += "\tfloat metallic_tex = texture(texture_metallic,base_uv).r;\n";
+ }
code += "\tMETALLIC = metallic_tex * metallic;\n";
- code += "\tfloat roughness_tex = texture(texture_roughness,base_uv).r;\n";
+ if (flags[FLAG_UV1_USE_TRIPLANAR]) {
+ code += "\tfloat roughness_tex = triplanar_texture(texture_roughness,uv1_power_normal,uv1_world_pos).r;\n";
+ } else {
+ code += "\tfloat roughness_tex = texture(texture_roughness,base_uv).r;\n";
+ }
code += "\tROUGHNESS = roughness_tex * roughness;\n";
code += "\tSPECULAR = specular;\n";
if (features[FEATURE_NORMAL_MAPPING]) {
- code += "\tNORMALMAP = texture(texture_normal,base_uv).rgb;\n";
+ if (flags[FLAG_UV1_USE_TRIPLANAR]) {
+ code += "\tNORMALMAP = triplanar_texture(texture_normal,uv1_power_normal,uv1_world_pos).rgb;\n";
+ } else {
+ code += "\tNORMALMAP = texture(texture_normal,base_uv).rgb;\n";
+ }
code += "\tNORMALMAP_DEPTH = normal_scale;\n";
}
if (features[FEATURE_EMISSION]) {
- code += "\tEMISSION = (emission.rgb+texture(texture_emission,base_uv).rgb)*emission_energy;\n";
+ if (flags[FLAG_UV1_USE_TRIPLANAR]) {
+ code += "\tvec3 emission_tex = triplanar_texture(texture_emission,uv1_power_normal,uv1_world_pos).rgb;\n";
+ } else {
+ code += "\tvec3 emission_tex = texture(texture_emission,base_uv).rgb;\n";
+ }
+ code += "\tEMISSION = (emission.rgb+emission_tex)*emission_energy;\n";
}
- if (features[FEATURE_REFRACTION]) {
+ if (features[FEATURE_REFRACTION] && !flags[FLAG_UV1_USE_TRIPLANAR]) { //refraction not supported with triplanar
if (features[FEATURE_NORMAL_MAPPING]) {
code += "\tvec3 ref_normal = normalize( mix(NORMAL,TANGENT * NORMALMAP.x + BINORMAL * NORMALMAP.y + NORMAL * NORMALMAP.z,NORMALMAP_DEPTH) ) * SIDE;\n";
@@ -532,38 +667,82 @@ void SpatialMaterial::_update_shader() {
}
if (features[FEATURE_RIM]) {
- code += "\tvec2 rim_tex = texture(texture_rim,base_uv).xw;\n";
+ if (flags[FLAG_UV1_USE_TRIPLANAR]) {
+ code += "\tvec2 rim_tex = triplanar_texture(texture_rim,uv1_power_normal,uv1_world_pos).xy;\n";
+ } else {
+ code += "\tvec2 rim_tex = texture(texture_rim,base_uv).xy;\n";
+ }
code += "\tRIM = rim*rim_tex.x;";
code += "\tRIM_TINT = rim_tint*rim_tex.y;\n";
}
if (features[FEATURE_CLEARCOAT]) {
- code += "\tvec2 clearcoat_tex = texture(texture_clearcoat,base_uv).xw;\n";
+ if (flags[FLAG_UV1_USE_TRIPLANAR]) {
+ code += "\tvec2 clearcoat_tex = triplanar_texture(texture_clearcoat,uv1_power_normal,uv1_world_pos).xy;\n";
+ } else {
+ code += "\tvec2 clearcoat_tex = texture(texture_clearcoat,base_uv).xy;\n";
+ }
code += "\tCLEARCOAT = clearcoat*clearcoat_tex.x;";
code += "\tCLEARCOAT_GLOSS = clearcoat_gloss*clearcoat_tex.y;\n";
}
if (features[FEATURE_ANISOTROPY]) {
- code += "\tvec4 anisotropy_tex = texture(texture_flowmap,base_uv);\n";
- code += "\tANISOTROPY = anisotropy_ratio*anisotropy_tex.a;\n";
+ if (flags[FLAG_UV1_USE_TRIPLANAR]) {
+ code += "\tvec3 anisotropy_tex = triplanar_texture(texture_flowmap,uv1_power_normal,uv1_world_pos).rga;\n";
+ } else {
+ code += "\tvec3 anisotropy_tex = texture(texture_flowmap,base_uv).rga;\n";
+ }
+ code += "\tANISOTROPY = anisotropy_ratio*anisotropy_tex.b;\n";
code += "\tANISOTROPY_FLOW = anisotropy_tex.rg*2.0-1.0;\n";
}
if (features[FEATURE_AMBIENT_OCCLUSION]) {
- code += "\tAO = texture(texture_ambient_occlusion,base_uv).r;\n";
+ if (flags[FLAG_AO_ON_UV2]) {
+ if (flags[FLAG_UV2_USE_TRIPLANAR]) {
+ code += "\tAO = triplanar_texture(texture_ambient_occlusion,uv2_power_normal,uv2_world_pos).r;\n";
+ } else {
+ code += "\tAO = texture(texture_ambient_occlusion,base_uv2).r;\n";
+ }
+ } else {
+ if (flags[FLAG_UV1_USE_TRIPLANAR]) {
+ code += "\tAO = triplanar_texture(texture_ambient_occlusion,uv1_power_normal,uv1_world_pos).r;\n";
+ } else {
+ code += "\tAO = texture(texture_ambient_occlusion,base_uv).r;\n";
+ }
+ }
}
if (features[FEATURE_SUBSURACE_SCATTERING]) {
- code += "\tfloat sss_tex = texture(texture_subsurface_scattering,base_uv).r;\n";
+ if (flags[FLAG_UV1_USE_TRIPLANAR]) {
+ code += "\tfloat sss_tex = triplanar_texture(texture_subsurface_scattering,uv1_power_normal,uv1_world_pos).r;\n";
+ } else {
+ code += "\tfloat sss_tex = texture(texture_subsurface_scattering,base_uv).r;\n";
+ }
code += "\tSSS_STRENGTH=subsurface_scattering_strength*sss_tex;\n";
}
if (features[FEATURE_DETAIL]) {
- String det_uv = detail_uv == DETAIL_UV_1 ? "base_uv" : "base_uv2";
- code += "\tvec4 detail_tex = texture(texture_detail_albedo," + det_uv + ");\n";
- code += "\tvec4 detail_norm_tex = texture(texture_detail_normal," + det_uv + ");\n";
- code += "\tvec4 detail_mask_tex = texture(texture_detail_mask,base_uv);\n";
+
+ bool triplanar = (flags[FLAG_UV1_USE_TRIPLANAR] && detail_uv == DETAIL_UV_1) || (flags[FLAG_UV2_USE_TRIPLANAR] && detail_uv == DETAIL_UV_2);
+
+ if (triplanar) {
+ String tp_uv = detail_uv == DETAIL_UV_1 ? "uv1" : "uv2";
+ code += "\tvec4 detail_tex = triplanar_texture(texture_detail_albedo," + tp_uv + "_power_normal," + tp_uv + "_world_pos);\n";
+ code += "\tvec4 detail_norm_tex = triplanar_texture(texture_detail_normal," + tp_uv + "_power_normal," + tp_uv + "_world_pos);\n";
+
+ } else {
+ String det_uv = detail_uv == DETAIL_UV_1 ? "base_uv" : "base_uv2";
+ code += "\tvec4 detail_tex = texture(texture_detail_albedo," + det_uv + ");\n";
+ code += "\tvec4 detail_norm_tex = texture(texture_detail_normal," + det_uv + ");\n";
+ }
+
+ if (flags[FLAG_UV1_USE_TRIPLANAR]) {
+
+ code += "\tvec4 detail_mask_tex = triplanar_texture(texture_detail_mask,uv1_power_normal);\n";
+ } else {
+ code += "\tvec4 detail_mask_tex = texture(texture_detail_mask,base_uv);\n";
+ }
switch (detail_blend_mode) {
case BLEND_MODE_MIX: {
@@ -581,7 +760,6 @@ void SpatialMaterial::_update_shader() {
}
code += "\tvec3 detail_norm = mix(NORMALMAP,detail_norm_tex.rgb,detail_tex.a);\n";
-
code += "\tNORMALMAP = mix(NORMALMAP,detail_norm,detail_mask_tex.r);\n";
code += "\tALBEDO.rgb = mix(ALBEDO.rgb,detail,detail_mask_tex.r);\n";
}
@@ -875,6 +1053,19 @@ SpatialMaterial::DiffuseMode SpatialMaterial::get_diffuse_mode() const {
return diffuse_mode;
}
+void SpatialMaterial::set_specular_mode(SpecularMode p_mode) {
+
+ if (specular_mode == p_mode)
+ return;
+
+ specular_mode = p_mode;
+ _queue_shader_change();
+}
+SpatialMaterial::SpecularMode SpatialMaterial::get_specular_mode() const {
+
+ return specular_mode;
+}
+
void SpatialMaterial::set_flag(Flags p_flag, bool p_enabled) {
ERR_FAIL_INDEX(p_flag, FLAG_MAX);
@@ -947,6 +1138,10 @@ void SpatialMaterial::_validate_property(PropertyInfo &property) const {
if (property.name.begins_with("particles_anim_") && billboard_mode != BILLBOARD_PARTICLES) {
property.usage = 0;
}
+
+ if (property.name == "params_grow_amount" && !grow_enabled) {
+ property.usage = 0;
+ }
}
void SpatialMaterial::set_line_width(float p_line_width) {
@@ -971,49 +1166,71 @@ float SpatialMaterial::get_point_size() const {
return point_size;
}
-void SpatialMaterial::set_uv1_scale(const Vector2 &p_scale) {
+void SpatialMaterial::set_uv1_scale(const Vector3 &p_scale) {
uv1_scale = p_scale;
VS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_scale, p_scale);
}
-Vector2 SpatialMaterial::get_uv1_scale() const {
+Vector3 SpatialMaterial::get_uv1_scale() const {
return uv1_scale;
}
-void SpatialMaterial::set_uv1_offset(const Vector2 &p_offset) {
+void SpatialMaterial::set_uv1_offset(const Vector3 &p_offset) {
uv1_offset = p_offset;
VS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_offset, p_offset);
}
-Vector2 SpatialMaterial::get_uv1_offset() const {
+Vector3 SpatialMaterial::get_uv1_offset() const {
return uv1_offset;
}
-void SpatialMaterial::set_uv2_scale(const Vector2 &p_scale) {
+void SpatialMaterial::set_uv1_triplanar_blend_sharpness(float p_sharpness) {
+
+ uv1_triplanar_sharpness = p_sharpness;
+ VS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_blend_sharpness, p_sharpness);
+}
+
+float SpatialMaterial::get_uv1_triplanar_blend_sharpness() const {
+
+ return uv1_triplanar_sharpness;
+}
+
+void SpatialMaterial::set_uv2_scale(const Vector3 &p_scale) {
uv2_scale = p_scale;
VS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_scale, p_scale);
}
-Vector2 SpatialMaterial::get_uv2_scale() const {
+Vector3 SpatialMaterial::get_uv2_scale() const {
return uv2_scale;
}
-void SpatialMaterial::set_uv2_offset(const Vector2 &p_offset) {
+void SpatialMaterial::set_uv2_offset(const Vector3 &p_offset) {
uv2_offset = p_offset;
VS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_offset, p_offset);
}
-Vector2 SpatialMaterial::get_uv2_offset() const {
+Vector3 SpatialMaterial::get_uv2_offset() const {
return uv2_offset;
}
+void SpatialMaterial::set_uv2_triplanar_blend_sharpness(float p_sharpness) {
+
+ uv2_triplanar_sharpness = p_sharpness;
+ VS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_blend_sharpness, p_sharpness);
+}
+
+float SpatialMaterial::get_uv2_triplanar_blend_sharpness() const {
+
+ return uv2_triplanar_sharpness;
+}
+
void SpatialMaterial::set_billboard_mode(BillboardMode p_mode) {
billboard_mode = p_mode;
@@ -1063,7 +1280,6 @@ void SpatialMaterial::set_depth_deep_parallax(bool p_enable) {
deep_parallax = p_enable;
_queue_shader_change();
_change_notify();
- ;
}
bool SpatialMaterial::is_depth_deep_parallax_enabled() const {
@@ -1091,6 +1307,26 @@ int SpatialMaterial::get_depth_deep_parallax_max_layers() const {
return deep_parallax_max_layers;
}
+void SpatialMaterial::set_grow_enabled(bool p_enable) {
+ grow_enabled = p_enable;
+ _queue_shader_change();
+ _change_notify();
+}
+
+bool SpatialMaterial::is_grow_enabled() const {
+ return grow_enabled;
+}
+
+void SpatialMaterial::set_grow(float p_grow) {
+ grow = p_grow;
+ VS::get_singleton()->material_set_param(_get_material(), shader_names->grow, p_grow);
+}
+
+float SpatialMaterial::get_grow() const {
+
+ return grow;
+}
+
void SpatialMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_albedo", "albedo"), &SpatialMaterial::set_albedo);
@@ -1159,14 +1395,17 @@ void SpatialMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_diffuse_mode", "diffuse_mode"), &SpatialMaterial::set_diffuse_mode);
ClassDB::bind_method(D_METHOD("get_diffuse_mode"), &SpatialMaterial::get_diffuse_mode);
+ ClassDB::bind_method(D_METHOD("set_specular_mode", "specular_mode"), &SpatialMaterial::set_specular_mode);
+ ClassDB::bind_method(D_METHOD("get_specular_mode"), &SpatialMaterial::get_specular_mode);
+
ClassDB::bind_method(D_METHOD("set_flag", "flag", "enable"), &SpatialMaterial::set_flag);
- ClassDB::bind_method(D_METHOD("get_flag"), &SpatialMaterial::get_flag);
+ ClassDB::bind_method(D_METHOD("get_flag", "flag"), &SpatialMaterial::get_flag);
ClassDB::bind_method(D_METHOD("set_feature", "feature", "enable"), &SpatialMaterial::set_feature);
ClassDB::bind_method(D_METHOD("get_feature", "feature"), &SpatialMaterial::get_feature);
- ClassDB::bind_method(D_METHOD("set_texture", "param:Texture", "texture"), &SpatialMaterial::set_texture);
- ClassDB::bind_method(D_METHOD("get_texture:Texture", "param:Texture"), &SpatialMaterial::get_texture);
+ ClassDB::bind_method(D_METHOD("set_texture", "param", "texture:Texture"), &SpatialMaterial::set_texture);
+ ClassDB::bind_method(D_METHOD("get_texture:Texture", "param"), &SpatialMaterial::get_texture);
ClassDB::bind_method(D_METHOD("set_detail_blend_mode", "detail_blend_mode"), &SpatialMaterial::set_detail_blend_mode);
ClassDB::bind_method(D_METHOD("get_detail_blend_mode"), &SpatialMaterial::get_detail_blend_mode);
@@ -1177,12 +1416,18 @@ void SpatialMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_uv1_offset", "offset"), &SpatialMaterial::set_uv1_offset);
ClassDB::bind_method(D_METHOD("get_uv1_offset"), &SpatialMaterial::get_uv1_offset);
+ ClassDB::bind_method(D_METHOD("set_uv1_triplanar_blend_sharpness", "sharpness"), &SpatialMaterial::set_uv1_triplanar_blend_sharpness);
+ ClassDB::bind_method(D_METHOD("get_uv1_triplanar_blend_sharpness"), &SpatialMaterial::get_uv1_triplanar_blend_sharpness);
+
ClassDB::bind_method(D_METHOD("set_uv2_scale", "scale"), &SpatialMaterial::set_uv2_scale);
ClassDB::bind_method(D_METHOD("get_uv2_scale"), &SpatialMaterial::get_uv2_scale);
ClassDB::bind_method(D_METHOD("set_uv2_offset", "offset"), &SpatialMaterial::set_uv2_offset);
ClassDB::bind_method(D_METHOD("get_uv2_offset"), &SpatialMaterial::get_uv2_offset);
+ ClassDB::bind_method(D_METHOD("set_uv2_triplanar_blend_sharpness", "sharpness"), &SpatialMaterial::set_uv2_triplanar_blend_sharpness);
+ ClassDB::bind_method(D_METHOD("get_uv2_triplanar_blend_sharpness"), &SpatialMaterial::get_uv2_triplanar_blend_sharpness);
+
ClassDB::bind_method(D_METHOD("set_billboard_mode", "mode"), &SpatialMaterial::set_billboard_mode);
ClassDB::bind_method(D_METHOD("get_billboard_mode"), &SpatialMaterial::get_billboard_mode);
@@ -1204,9 +1449,16 @@ void SpatialMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_depth_deep_parallax_max_layers", "layer"), &SpatialMaterial::set_depth_deep_parallax_max_layers);
ClassDB::bind_method(D_METHOD("get_depth_deep_parallax_max_layers"), &SpatialMaterial::get_depth_deep_parallax_max_layers);
+ ClassDB::bind_method(D_METHOD("set_grow", "amount"), &SpatialMaterial::set_grow);
+ ClassDB::bind_method(D_METHOD("get_grow"), &SpatialMaterial::get_grow);
+
+ ClassDB::bind_method(D_METHOD("set_grow_enabled", "enable"), &SpatialMaterial::set_grow_enabled);
+ ClassDB::bind_method(D_METHOD("is_grow_enabled"), &SpatialMaterial::is_grow_enabled);
+
ADD_GROUP("Flags", "flags_");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_transparent"), "set_feature", "get_feature", FEATURE_TRANSPARENT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_unshaded"), "set_flag", "get_flag", FLAG_UNSHADED);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_vertex_lighting"), "set_flag", "get_flag", FLAG_USE_VERTEX_LIGHTING);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_on_top"), "set_flag", "get_flag", FLAG_ONTOP);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_use_point_size"), "set_flag", "get_flag", FLAG_USE_POINT_SIZE);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_fixed_size"), "set_flag", "get_flag", FLAG_FIXED_SIZE);
@@ -1215,13 +1467,16 @@ void SpatialMaterial::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "vertex_color_is_srgb"), "set_flag", "get_flag", FLAG_SRGB_VERTEX_COLOR);
ADD_GROUP("Parameters", "params_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "params_diffuse_mode", PROPERTY_HINT_ENUM, "Lambert,Lambert Wrap,Oren Nayar,Burley"), "set_diffuse_mode", "get_diffuse_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "params_diffuse_mode", PROPERTY_HINT_ENUM, "Lambert,Lambert Wrap,Oren Nayar,Burley,Toon"), "set_diffuse_mode", "get_diffuse_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "params_specular_mode", PROPERTY_HINT_ENUM, "SchlickGGX,Blinn,Phong,Toon,Disabled"), "set_specular_mode", "get_specular_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "params_blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul"), "set_blend_mode", "get_blend_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "params_cull_mode", PROPERTY_HINT_ENUM, "Back,Front,Disabled"), "set_cull_mode", "get_cull_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "params_depth_draw_mode", PROPERTY_HINT_ENUM, "Opaque Only,Always,Never,Opaque Pre-Pass"), "set_depth_draw_mode", "get_depth_draw_mode");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_line_width", PROPERTY_HINT_RANGE, "0.1,128,0.1"), "set_line_width", "get_line_width");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_point_size", PROPERTY_HINT_RANGE, "0.1,128,0.1"), "set_point_size", "get_point_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "params_billboard_mode", PROPERTY_HINT_ENUM, "Disabled,Enabled,Y-Billboard,Particle Billboard"), "set_billboard_mode", "get_billboard_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "params_grow"), "set_grow_enabled", "is_grow_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_grow_amount", PROPERTY_HINT_RANGE, "-16,10,0.01"), "set_grow", "get_grow");
ADD_GROUP("Particles Anim", "particles_anim_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "particles_anim_h_frames", PROPERTY_HINT_RANGE, "1,128,1"), "set_particles_anim_h_frames", "get_particles_anim_h_frames");
ADD_PROPERTY(PropertyInfo(Variant::INT, "particles_anim_v_frames", PROPERTY_HINT_RANGE, "1,128,1"), "set_particles_anim_v_frames", "get_particles_anim_v_frames");
@@ -1265,12 +1520,13 @@ void SpatialMaterial::_bind_methods() {
ADD_GROUP("Anisotropy", "anisotropy_");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "anisotropy_enabled"), "set_feature", "get_feature", FEATURE_ANISOTROPY);
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "anisotropy", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_anisotropy", "get_anisotropy");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "anisotropy", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_anisotropy", "get_anisotropy");
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anisotropy_flowmap", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_FLOWMAP);
ADD_GROUP("Ambient Occlusion", "ao_");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "ao_enabled"), "set_feature", "get_feature", FEATURE_AMBIENT_OCCLUSION);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "ao_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_AMBIENT_OCCLUSION);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "ao_on_uv2"), "set_flag", "get_flag", FLAG_AO_ON_UV2);
ADD_GROUP("Depth", "depth_");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "depth_enabled"), "set_feature", "get_feature", FEATURE_DEPTH_MAPPING);
@@ -1299,12 +1555,16 @@ void SpatialMaterial::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "detail_normal", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_DETAIL_NORMAL);
ADD_GROUP("UV1", "uv1_");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "uv1_scale"), "set_uv1_scale", "get_uv1_scale");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "uv1_offset"), "set_uv1_offset", "get_uv1_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv1_scale"), "set_uv1_scale", "get_uv1_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv1_offset"), "set_uv1_offset", "get_uv1_offset");
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "uv1_triplanar"), "set_flag", "get_flag", FLAG_UV1_USE_TRIPLANAR);
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "uv1_triplanar_sharpness", PROPERTY_HINT_EXP_EASING), "set_uv1_triplanar_blend_sharpness", "get_uv1_triplanar_blend_sharpness");
ADD_GROUP("UV2", "uv2_");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "uv2_scale"), "set_uv2_scale", "get_uv2_scale");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "uv2_offset"), "set_uv2_offset", "get_uv2_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv2_scale"), "set_uv2_scale", "get_uv2_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv2_offset"), "set_uv2_offset", "get_uv2_offset");
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "uv2_triplanar"), "set_flag", "get_flag", FLAG_UV2_USE_TRIPLANAR);
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "uv2_triplanar_sharpness", PROPERTY_HINT_EXP_EASING), "set_uv2_triplanar_blend_sharpness", "get_uv2_triplanar_blend_sharpness");
BIND_CONSTANT(TEXTURE_ALBEDO);
BIND_CONSTANT(TEXTURE_METALLIC);
@@ -1354,6 +1614,7 @@ void SpatialMaterial::_bind_methods() {
BIND_CONSTANT(CULL_DISABLED);
BIND_CONSTANT(FLAG_UNSHADED);
+ BIND_CONSTANT(FLAG_USE_VERTEX_LIGHTING);
BIND_CONSTANT(FLAG_ONTOP);
BIND_CONSTANT(FLAG_ALBEDO_FROM_VERTEX_COLOR);
BIND_CONSTANT(FLAG_SRGB_VERTEX_COLOR)
@@ -1365,6 +1626,13 @@ void SpatialMaterial::_bind_methods() {
BIND_CONSTANT(DIFFUSE_HALF_LAMBERT);
BIND_CONSTANT(DIFFUSE_OREN_NAYAR);
BIND_CONSTANT(DIFFUSE_BURLEY);
+ BIND_CONSTANT(DIFFUSE_TOON);
+
+ BIND_CONSTANT(SPECULAR_SCHLICK_GGX);
+ BIND_CONSTANT(SPECULAR_BLINN);
+ BIND_CONSTANT(SPECULAR_PHONG);
+ BIND_CONSTANT(SPECULAR_TOON);
+ BIND_CONSTANT(SPECULAR_DISABLED);
BIND_CONSTANT(BILLBOARD_DISABLED);
BIND_CONSTANT(BILLBOARD_ENABLED);
@@ -1393,15 +1661,20 @@ SpatialMaterial::SpatialMaterial()
set_refraction(0.05);
set_line_width(1);
set_point_size(1);
- set_uv1_offset(Vector2(0, 0));
- set_uv1_scale(Vector2(1, 1));
- set_uv2_offset(Vector2(0, 0));
- set_uv2_scale(Vector2(1, 1));
+ set_uv1_offset(Vector3(0, 0, 0));
+ set_uv1_scale(Vector3(1, 1, 1));
+ set_uv1_triplanar_blend_sharpness(1);
+ set_uv2_offset(Vector3(0, 0, 0));
+ set_uv2_scale(Vector3(1, 1, 1));
+ set_uv2_triplanar_blend_sharpness(1);
set_billboard_mode(BILLBOARD_DISABLED);
set_particles_anim_h_frames(1);
set_particles_anim_v_frames(1);
set_particles_anim_loop(false);
+ grow_enabled = false;
+ set_grow(0.0);
+
deep_parallax = false;
set_depth_deep_parallax_min_layers(8);
set_depth_deep_parallax_max_layers(32);
@@ -1415,6 +1688,7 @@ SpatialMaterial::SpatialMaterial()
flags[i] = 0;
}
diffuse_mode = DIFFUSE_LAMBERT;
+ specular_mode = SPECULAR_SCHLICK_GGX;
for (int i = 0; i < FEATURE_MAX; i++) {
features[i] = false;
diff --git a/scene/resources/material.h b/scene/resources/material.h
index fb6c5b81d9..7587fc7927 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -47,11 +47,16 @@ class Material : public Resource {
OBJ_SAVE_TYPE(Material)
RID material;
+ Ref<Material> next_pass;
protected:
_FORCE_INLINE_ RID _get_material() const { return material; }
+ static void _bind_methods();
public:
+ void set_next_pass(const Ref<Material> &p_pass);
+ Ref<Material> get_next_pass() const;
+
virtual RID get_rid() const;
Material();
virtual ~Material();
@@ -150,11 +155,15 @@ public:
enum Flags {
FLAG_UNSHADED,
+ FLAG_USE_VERTEX_LIGHTING,
FLAG_ONTOP,
FLAG_ALBEDO_FROM_VERTEX_COLOR,
FLAG_SRGB_VERTEX_COLOR,
FLAG_USE_POINT_SIZE,
FLAG_FIXED_SIZE,
+ FLAG_UV1_USE_TRIPLANAR,
+ FLAG_UV2_USE_TRIPLANAR,
+ FLAG_AO_ON_UV2,
FLAG_MAX
};
@@ -163,6 +172,15 @@ public:
DIFFUSE_HALF_LAMBERT,
DIFFUSE_OREN_NAYAR,
DIFFUSE_BURLEY,
+ DIFFUSE_TOON,
+ };
+
+ enum SpecularMode {
+ SPECULAR_SCHLICK_GGX,
+ SPECULAR_BLINN,
+ SPECULAR_PHONG,
+ SPECULAR_TOON,
+ SPECULAR_DISABLED,
};
enum BillboardMode {
@@ -176,20 +194,22 @@ private:
union MaterialKey {
struct {
- uint32_t feature_mask : 11;
- uint32_t detail_uv : 1;
- uint32_t blend_mode : 2;
- uint32_t depth_draw_mode : 2;
- uint32_t cull_mode : 2;
- uint32_t flags : 6;
- uint32_t detail_blend_mode : 2;
- uint32_t diffuse_mode : 2;
- uint32_t invalid_key : 1;
- uint32_t deep_parallax : 1;
- uint32_t billboard_mode : 2;
+ uint64_t feature_mask : 11;
+ uint64_t detail_uv : 1;
+ uint64_t blend_mode : 2;
+ uint64_t depth_draw_mode : 2;
+ uint64_t cull_mode : 2;
+ uint64_t flags : 9;
+ uint64_t detail_blend_mode : 2;
+ uint64_t diffuse_mode : 3;
+ uint64_t specular_mode : 2;
+ uint64_t invalid_key : 1;
+ uint64_t deep_parallax : 1;
+ uint64_t billboard_mode : 2;
+ uint64_t grow : 1;
};
- uint32_t key;
+ uint64_t key;
bool operator<(const MaterialKey &p_key) const {
return key < p_key.key;
@@ -225,9 +245,10 @@ private:
}
mk.detail_blend_mode = detail_blend_mode;
mk.diffuse_mode = diffuse_mode;
+ mk.specular_mode = specular_mode;
mk.billboard_mode = billboard_mode;
mk.deep_parallax = deep_parallax ? 1 : 0;
- ;
+ mk.grow = grow_enabled;
return mk;
}
@@ -258,6 +279,9 @@ private:
StringName particles_anim_loop;
StringName depth_min_layers;
StringName depth_max_layers;
+ StringName uv1_blend_sharpness;
+ StringName uv2_blend_sharpness;
+ StringName grow;
StringName texture_names[TEXTURE_MAX];
};
@@ -289,15 +313,19 @@ private:
float refraction;
float line_width;
float point_size;
+ bool grow_enabled;
+ float grow;
int particles_anim_h_frames;
int particles_anim_v_frames;
bool particles_anim_loop;
- Vector2 uv1_scale;
- Vector2 uv1_offset;
+ Vector3 uv1_scale;
+ Vector3 uv1_offset;
+ float uv1_triplanar_sharpness;
- Vector2 uv2_scale;
- Vector2 uv2_offset;
+ Vector3 uv2_scale;
+ Vector3 uv2_offset;
+ float uv2_triplanar_sharpness;
DetailUV detail_uv;
@@ -310,6 +338,7 @@ private:
DepthDrawMode depth_draw_mode;
CullMode cull_mode;
bool flags[FLAG_MAX];
+ SpecularMode specular_mode;
DiffuseMode diffuse_mode;
BillboardMode billboard_mode;
@@ -402,6 +431,9 @@ public:
void set_diffuse_mode(DiffuseMode p_mode);
DiffuseMode get_diffuse_mode() const;
+ void set_specular_mode(SpecularMode p_mode);
+ SpecularMode get_specular_mode() const;
+
void set_flag(Flags p_flag, bool p_enabled);
bool get_flag(Flags p_flag) const;
@@ -411,17 +443,23 @@ public:
void set_feature(Feature p_feature, bool p_enabled);
bool get_feature(Feature p_feature) const;
- void set_uv1_scale(const Vector2 &p_scale);
- Vector2 get_uv1_scale() const;
+ void set_uv1_scale(const Vector3 &p_scale);
+ Vector3 get_uv1_scale() const;
- void set_uv1_offset(const Vector2 &p_offset);
- Vector2 get_uv1_offset() const;
+ void set_uv1_offset(const Vector3 &p_offset);
+ Vector3 get_uv1_offset() const;
- void set_uv2_scale(const Vector2 &p_scale);
- Vector2 get_uv2_scale() const;
+ void set_uv1_triplanar_blend_sharpness(float p_sharpness);
+ float get_uv1_triplanar_blend_sharpness() const;
- void set_uv2_offset(const Vector2 &p_offset);
- Vector2 get_uv2_offset() const;
+ void set_uv2_scale(const Vector3 &p_scale);
+ Vector3 get_uv2_scale() const;
+
+ void set_uv2_offset(const Vector3 &p_offset);
+ Vector3 get_uv2_offset() const;
+
+ void set_uv2_triplanar_blend_sharpness(float p_sharpness);
+ float get_uv2_triplanar_blend_sharpness() const;
void set_billboard_mode(BillboardMode p_mode);
BillboardMode get_billboard_mode() const;
@@ -434,6 +472,12 @@ public:
void set_particles_anim_loop(int p_frames);
int get_particles_anim_loop() const;
+ void set_grow_enabled(bool p_enable);
+ bool is_grow_enabled() const;
+
+ void set_grow(float p_grow);
+ float get_grow() const;
+
static void init_shaders();
static void finish_shaders();
static void flush_changes();
@@ -450,6 +494,7 @@ VARIANT_ENUM_CAST(SpatialMaterial::DepthDrawMode)
VARIANT_ENUM_CAST(SpatialMaterial::CullMode)
VARIANT_ENUM_CAST(SpatialMaterial::Flags)
VARIANT_ENUM_CAST(SpatialMaterial::DiffuseMode)
+VARIANT_ENUM_CAST(SpatialMaterial::SpecularMode)
VARIANT_ENUM_CAST(SpatialMaterial::BillboardMode)
//////////////////////
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index ef7011b2af..310ab5e371 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -32,7 +32,7 @@
#include "scene/resources/convex_polygon_shape.h"
#include "surface_tool.h"
-void Mesh::_clear_triangle_mesh() {
+void Mesh::_clear_triangle_mesh() const {
triangle_mesh.unref();
;
@@ -413,6 +413,17 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const {
return newmesh;
}
+void Mesh::_bind_methods() {
+
+ BIND_CONSTANT(PRIMITIVE_POINTS);
+ BIND_CONSTANT(PRIMITIVE_LINES);
+ BIND_CONSTANT(PRIMITIVE_LINE_STRIP);
+ BIND_CONSTANT(PRIMITIVE_LINE_LOOP);
+ BIND_CONSTANT(PRIMITIVE_TRIANGLES);
+ BIND_CONSTANT(PRIMITIVE_TRIANGLE_STRIP);
+ BIND_CONSTANT(PRIMITIVE_TRIANGLE_FAN);
+}
+
Mesh::Mesh() {
}
@@ -1034,14 +1045,6 @@ void ArrayMesh::_bind_methods() {
BIND_CONSTANT(ARRAY_FORMAT_BONES);
BIND_CONSTANT(ARRAY_FORMAT_WEIGHTS);
BIND_CONSTANT(ARRAY_FORMAT_INDEX);
-
- BIND_CONSTANT(PRIMITIVE_POINTS);
- BIND_CONSTANT(PRIMITIVE_LINES);
- BIND_CONSTANT(PRIMITIVE_LINE_STRIP);
- BIND_CONSTANT(PRIMITIVE_LINE_LOOP);
- BIND_CONSTANT(PRIMITIVE_TRIANGLES);
- BIND_CONSTANT(PRIMITIVE_TRIANGLE_STRIP);
- BIND_CONSTANT(PRIMITIVE_TRIANGLE_FAN);
}
ArrayMesh::ArrayMesh() {
diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h
index f716b59fe9..e40ef99237 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -44,7 +44,9 @@ class Mesh : public Resource {
mutable Ref<TriangleMesh> triangle_mesh; //cached
protected:
- void _clear_triangle_mesh();
+ void _clear_triangle_mesh() const;
+
+ static void _bind_methods();
public:
enum {
diff --git a/scene/resources/mesh_data_tool.cpp b/scene/resources/mesh_data_tool.cpp
index dc3713fb57..5dc596abff 100644
--- a/scene/resources/mesh_data_tool.cpp
+++ b/scene/resources/mesh_data_tool.cpp
@@ -520,8 +520,8 @@ void MeshDataTool::set_material(const Ref<Material> &p_material) {
void MeshDataTool::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear"), &MeshDataTool::clear);
- ClassDB::bind_method(D_METHOD("create_from_surface", "mesh", "surface"), &MeshDataTool::create_from_surface);
- ClassDB::bind_method(D_METHOD("commit_to_surface", "mesh"), &MeshDataTool::commit_to_surface);
+ ClassDB::bind_method(D_METHOD("create_from_surface", "mesh:ArrayMesh", "surface"), &MeshDataTool::create_from_surface);
+ ClassDB::bind_method(D_METHOD("commit_to_surface", "mesh:ArrayMesh"), &MeshDataTool::commit_to_surface);
ClassDB::bind_method(D_METHOD("get_format"), &MeshDataTool::get_format);
@@ -554,7 +554,7 @@ void MeshDataTool::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_vertex_weights", "idx"), &MeshDataTool::get_vertex_weights);
ClassDB::bind_method(D_METHOD("set_vertex_meta", "idx", "meta"), &MeshDataTool::set_vertex_meta);
- ClassDB::bind_method(D_METHOD("get_vertex_meta", "idx"), &MeshDataTool::get_vertex_meta);
+ ClassDB::bind_method(D_METHOD("get_vertex_meta:Variant", "idx"), &MeshDataTool::get_vertex_meta);
ClassDB::bind_method(D_METHOD("get_vertex_edges", "idx"), &MeshDataTool::get_vertex_edges);
ClassDB::bind_method(D_METHOD("get_vertex_faces", "idx"), &MeshDataTool::get_vertex_faces);
@@ -563,18 +563,18 @@ void MeshDataTool::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_edge_faces", "idx", "faces"), &MeshDataTool::get_edge_faces);
ClassDB::bind_method(D_METHOD("set_edge_meta", "idx", "meta"), &MeshDataTool::set_edge_meta);
- ClassDB::bind_method(D_METHOD("get_edge_meta", "idx"), &MeshDataTool::get_edge_meta);
+ ClassDB::bind_method(D_METHOD("get_edge_meta:Variant", "idx"), &MeshDataTool::get_edge_meta);
ClassDB::bind_method(D_METHOD("get_face_vertex", "idx", "vertex"), &MeshDataTool::get_face_vertex);
ClassDB::bind_method(D_METHOD("get_face_edge", "idx", "edge"), &MeshDataTool::get_face_edge);
ClassDB::bind_method(D_METHOD("set_face_meta", "idx", "meta"), &MeshDataTool::set_face_meta);
- ClassDB::bind_method(D_METHOD("get_face_meta", "idx"), &MeshDataTool::get_face_meta);
+ ClassDB::bind_method(D_METHOD("get_face_meta:Variant", "idx"), &MeshDataTool::get_face_meta);
ClassDB::bind_method(D_METHOD("get_face_normal", "idx"), &MeshDataTool::get_face_normal);
ClassDB::bind_method(D_METHOD("set_material", "material:Material"), &MeshDataTool::set_material);
- ClassDB::bind_method(D_METHOD("get_material", "material"), &MeshDataTool::get_material);
+ ClassDB::bind_method(D_METHOD("get_material:Material", "material"), &MeshDataTool::get_material);
}
MeshDataTool::MeshDataTool() {
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index 50fbb6a162..6bf3590c12 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -29,8 +29,8 @@
/*************************************************************************/
#include "packed_scene.h"
#include "core/core_string_names.h"
-#include "global_config.h"
#include "io/resource_loader.h"
+#include "project_settings.h"
#include "scene/2d/node_2d.h"
#include "scene/3d/spatial.h"
#include "scene/gui/control.h"
@@ -1671,7 +1671,7 @@ void SceneState::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_node_groups", "idx"), &SceneState::_get_node_groups);
ClassDB::bind_method(D_METHOD("get_node_property_count", "idx"), &SceneState::get_node_property_count);
ClassDB::bind_method(D_METHOD("get_node_property_name", "idx", "prop_idx"), &SceneState::get_node_property_name);
- ClassDB::bind_method(D_METHOD("get_node_property_value", "idx", "prop_idx"), &SceneState::get_node_property_value);
+ ClassDB::bind_method(D_METHOD("get_node_property_value:Variant", "idx", "prop_idx"), &SceneState::get_node_property_value);
ClassDB::bind_method(D_METHOD("get_connection_count"), &SceneState::get_connection_count);
ClassDB::bind_method(D_METHOD("get_connection_source", "idx"), &SceneState::get_connection_source);
ClassDB::bind_method(D_METHOD("get_connection_signal", "idx"), &SceneState::get_connection_signal);
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index 8d058377db..327de2f6f3 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -34,34 +34,44 @@
/**
PrimitiveMesh
*/
-void PrimitiveMesh::_update() {
- if (!cache_is_dirty)
- return;
+void PrimitiveMesh::_update() const {
Array arr;
arr.resize(VS::ARRAY_MAX);
_create_mesh_array(arr);
+ PoolVector<Vector3> points = arr[VS::ARRAY_VERTEX];
+
+ aabb = Rect3();
+
+ int pc = points.size();
+ ERR_FAIL_COND(pc == 0);
+ {
+
+ PoolVector<Vector3>::Read r = points.read();
+ for (int i = 0; i < pc; i++) {
+ if (i == 0)
+ aabb.position = r[i];
+ else
+ aabb.expand_to(r[i]);
+ }
+ }
+
// in with the new
VisualServer::get_singleton()->mesh_clear(mesh);
VisualServer::get_singleton()->mesh_add_surface_from_arrays(mesh, (VisualServer::PrimitiveType)primitive_type, arr);
VisualServer::get_singleton()->mesh_surface_set_material(mesh, 0, material.is_null() ? RID() : material->get_rid());
- cache_is_dirty = false;
+ pending_request = false;
_clear_triangle_mesh();
- emit_changed();
}
-void PrimitiveMesh::_queue_update() {
- if (!cache_is_dirty) {
- cache_is_dirty = true;
- call_deferred("_update");
- }
-}
+void PrimitiveMesh::_request_update() {
-void PrimitiveMesh::set_aabb(Rect3 p_aabb) {
- aabb = p_aabb;
+ if (pending_request)
+ return;
+ _update();
}
int PrimitiveMesh::get_surface_count() const {
@@ -70,21 +80,37 @@ int PrimitiveMesh::get_surface_count() const {
int PrimitiveMesh::surface_get_array_len(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, 1, -1);
+ if (pending_request) {
+ _update();
+ }
+
return VisualServer::get_singleton()->mesh_surface_get_array_len(mesh, 0);
}
int PrimitiveMesh::surface_get_array_index_len(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, 1, -1);
+ if (pending_request) {
+ _update();
+ }
+
return VisualServer::get_singleton()->mesh_surface_get_array_index_len(mesh, 0);
}
Array PrimitiveMesh::surface_get_arrays(int p_surface) const {
ERR_FAIL_INDEX_V(p_surface, 1, Array());
+ if (pending_request) {
+ _update();
+ }
+
return VisualServer::get_singleton()->mesh_surface_get_arrays(mesh, 0);
}
uint32_t PrimitiveMesh::surface_get_format(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, 1, 0);
+ if (pending_request) {
+ _update();
+ }
+
return VisualServer::get_singleton()->mesh_surface_get_format(mesh, 0);
}
@@ -105,10 +131,17 @@ StringName PrimitiveMesh::get_blend_shape_name(int p_index) const {
}
Rect3 PrimitiveMesh::get_aabb() const {
+ if (pending_request) {
+ _update();
+ }
+
return aabb;
}
RID PrimitiveMesh::get_rid() const {
+ if (pending_request) {
+ _update();
+ }
return mesh;
}
@@ -123,10 +156,9 @@ void PrimitiveMesh::_bind_methods() {
void PrimitiveMesh::set_material(const Ref<Material> &p_material) {
material = p_material;
- if (!cache_is_dirty) {
+ if (!pending_request) {
// just apply it, else it'll happen when _update is called.
VisualServer::get_singleton()->mesh_surface_set_material(mesh, 0, material.is_null() ? RID() : material->get_rid());
-
_change_notify();
emit_changed();
};
@@ -144,8 +176,7 @@ PrimitiveMesh::PrimitiveMesh() {
primitive_type = Mesh::PRIMITIVE_TRIANGLES;
// make sure we do an update after we've finished constructing our object
- cache_is_dirty = false;
- _queue_update();
+ pending_request = true;
}
PrimitiveMesh::~PrimitiveMesh() {
@@ -156,13 +187,13 @@ PrimitiveMesh::~PrimitiveMesh() {
CapsuleMesh
*/
-void CapsuleMesh::_create_mesh_array(Array &p_arr) {
+void CapsuleMesh::_create_mesh_array(Array &p_arr) const {
int i, j, prevrow, thisrow, point;
float x, y, z, u, v, w;
float onethird = 1.0 / 3.0;
float twothirds = 2.0 / 3.0;
- set_aabb(Rect3(Vector3(-radius, (mid_height * -0.5) - radius, -radius), Vector3(radius * 2.0, mid_height + (2.0 * radius), radius * 2.0)));
+ // note, this has been aligned with our collision shape but I've left the descriptions as top/middle/bottom
PoolVector<Vector3> points;
PoolVector<Vector3> normals;
@@ -186,19 +217,19 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) {
v /= (rings + 1);
w = sin(0.5 * Math_PI * v);
- y = radius * cos(0.5 * Math_PI * v);
+ z = radius * cos(0.5 * Math_PI * v);
for (i = 0; i <= radial_segments; i++) {
u = i;
u /= radial_segments;
x = sin(u * (Math_PI * 2.0));
- z = cos(u * (Math_PI * 2.0));
+ y = -cos(u * (Math_PI * 2.0));
- Vector3 p = Vector3(x * radius * w, y, z * radius * w);
- points.push_back(p + Vector3(0.0, 0.5 * mid_height, 0.0));
+ Vector3 p = Vector3(x * radius * w, y * radius * w, z);
+ points.push_back(p + Vector3(0.0, 0.0, 0.5 * mid_height));
normals.push_back(p.normalized());
- ADD_TANGENT(-z, 0.0, x, -1.0)
+ ADD_TANGENT(y, -x, 0.0, -1.0)
uvs.push_back(Vector2(u, v * onethird));
point++;
@@ -224,20 +255,20 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) {
v = j;
v /= (rings + 1);
- y = mid_height * v;
- y = (mid_height * 0.5) - y;
+ z = mid_height * v;
+ z = (mid_height * 0.5) - z;
for (i = 0; i <= radial_segments; i++) {
u = i;
u /= radial_segments;
x = sin(u * (Math_PI * 2.0));
- z = cos(u * (Math_PI * 2.0));
+ y = -cos(u * (Math_PI * 2.0));
- Vector3 p = Vector3(x * radius, y, z * radius);
+ Vector3 p = Vector3(x * radius, y * radius, z);
points.push_back(p);
- normals.push_back(Vector3(x, 0.0, z));
- ADD_TANGENT(-z, 0.0, x, -1.0)
+ normals.push_back(Vector3(x, y, 0.0));
+ ADD_TANGENT(y, -x, 0.0, -1.0)
uvs.push_back(Vector2(u, onethird + (v * onethird)));
point++;
@@ -266,19 +297,19 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) {
v /= (rings + 1);
v += 1.0;
w = sin(0.5 * Math_PI * v);
- y = radius * cos(0.5 * Math_PI * v);
+ z = radius * cos(0.5 * Math_PI * v);
for (i = 0; i <= radial_segments; i++) {
float u = i;
u /= radial_segments;
x = sin(u * (Math_PI * 2.0));
- z = cos(u * (Math_PI * 2.0));
+ y = -cos(u * (Math_PI * 2.0));
- Vector3 p = Vector3(x * radius * w, y, z * radius * w);
- points.push_back(p + Vector3(0.0, -0.5 * mid_height, 0.0));
+ Vector3 p = Vector3(x * radius * w, y * radius * w, z);
+ points.push_back(p + Vector3(0.0, 0.0, -0.5 * mid_height));
normals.push_back(p.normalized());
- ADD_TANGENT(-z, 0.0, x, -1.0)
+ ADD_TANGENT(y, -x, 0.0, -1.0)
uvs.push_back(Vector2(u, twothirds + ((v - 1.0) * onethird)));
point++;
@@ -323,7 +354,7 @@ void CapsuleMesh::_bind_methods() {
void CapsuleMesh::set_radius(const float p_radius) {
radius = p_radius;
- _queue_update();
+ _request_update();
}
float CapsuleMesh::get_radius() const {
@@ -332,7 +363,7 @@ float CapsuleMesh::get_radius() const {
void CapsuleMesh::set_mid_height(const float p_mid_height) {
mid_height = p_mid_height;
- _queue_update();
+ _request_update();
}
float CapsuleMesh::get_mid_height() const {
@@ -341,7 +372,7 @@ float CapsuleMesh::get_mid_height() const {
void CapsuleMesh::set_radial_segments(const int p_segments) {
radial_segments = p_segments > 4 ? p_segments : 4;
- _queue_update();
+ _request_update();
}
int CapsuleMesh::get_radial_segments() const {
@@ -350,7 +381,7 @@ int CapsuleMesh::get_radial_segments() const {
void CapsuleMesh::set_rings(const int p_rings) {
rings = p_rings > 1 ? p_rings : 1;
- _queue_update();
+ _request_update();
}
int CapsuleMesh::get_rings() const {
@@ -369,7 +400,7 @@ CapsuleMesh::CapsuleMesh() {
CubeMesh
*/
-void CubeMesh::_create_mesh_array(Array &p_arr) {
+void CubeMesh::_create_mesh_array(Array &p_arr) const {
int i, j, prevrow, thisrow, point;
float x, y, z;
float onethird = 1.0 / 3.0;
@@ -378,7 +409,6 @@ void CubeMesh::_create_mesh_array(Array &p_arr) {
Vector3 start_pos = size * -0.5;
// set our bounding box
- set_aabb(Rect3(start_pos, size));
PoolVector<Vector3> points;
PoolVector<Vector3> normals;
@@ -581,7 +611,7 @@ void CubeMesh::_bind_methods() {
void CubeMesh::set_size(const Vector3 &p_size) {
size = p_size;
- _queue_update();
+ _request_update();
}
Vector3 CubeMesh::get_size() const {
@@ -590,7 +620,7 @@ Vector3 CubeMesh::get_size() const {
void CubeMesh::set_subdivide_width(const int p_subdivide) {
subdivide_w = p_subdivide > 0 ? p_subdivide : 0;
- _queue_update();
+ _request_update();
}
int CubeMesh::get_subdivide_width() const {
@@ -599,7 +629,7 @@ int CubeMesh::get_subdivide_width() const {
void CubeMesh::set_subdivide_height(const int p_subdivide) {
subdivide_h = p_subdivide > 0 ? p_subdivide : 0;
- _queue_update();
+ _request_update();
}
int CubeMesh::get_subdivide_height() const {
@@ -608,7 +638,7 @@ int CubeMesh::get_subdivide_height() const {
void CubeMesh::set_subdivide_depth(const int p_subdivide) {
subdivide_d = p_subdivide > 0 ? p_subdivide : 0;
- _queue_update();
+ _request_update();
}
int CubeMesh::get_subdivide_depth() const {
@@ -627,14 +657,12 @@ CubeMesh::CubeMesh() {
CylinderMesh
*/
-void CylinderMesh::_create_mesh_array(Array &p_arr) {
+void CylinderMesh::_create_mesh_array(Array &p_arr) const {
int i, j, prevrow, thisrow, point;
float x, y, z, u, v, radius;
radius = bottom_radius > top_radius ? bottom_radius : top_radius;
- set_aabb(Rect3(Vector3(-radius, height * -0.5, -radius), Vector3(radius * 2.0, height, radius * 2.0)));
-
PoolVector<Vector3> points;
PoolVector<Vector3> normals;
PoolVector<float> tangents;
@@ -789,7 +817,7 @@ void CylinderMesh::_bind_methods() {
void CylinderMesh::set_top_radius(const float p_radius) {
top_radius = p_radius;
- _queue_update();
+ _request_update();
}
float CylinderMesh::get_top_radius() const {
@@ -798,7 +826,7 @@ float CylinderMesh::get_top_radius() const {
void CylinderMesh::set_bottom_radius(const float p_radius) {
bottom_radius = p_radius;
- _queue_update();
+ _request_update();
}
float CylinderMesh::get_bottom_radius() const {
@@ -807,7 +835,7 @@ float CylinderMesh::get_bottom_radius() const {
void CylinderMesh::set_height(const float p_height) {
height = p_height;
- _queue_update();
+ _request_update();
}
float CylinderMesh::get_height() const {
@@ -816,7 +844,7 @@ float CylinderMesh::get_height() const {
void CylinderMesh::set_radial_segments(const int p_segments) {
radial_segments = p_segments > 4 ? p_segments : 4;
- _queue_update();
+ _request_update();
}
int CylinderMesh::get_radial_segments() const {
@@ -825,7 +853,7 @@ int CylinderMesh::get_radial_segments() const {
void CylinderMesh::set_rings(const int p_rings) {
rings = p_rings > 0 ? p_rings : 0;
- _queue_update();
+ _request_update();
}
int CylinderMesh::get_rings() const {
@@ -845,14 +873,12 @@ CylinderMesh::CylinderMesh() {
PlaneMesh
*/
-void PlaneMesh::_create_mesh_array(Array &p_arr) {
+void PlaneMesh::_create_mesh_array(Array &p_arr) const {
int i, j, prevrow, thisrow, point;
float x, z;
Size2 start_pos = size * -0.5;
- set_aabb(Rect3(Vector3(start_pos.x, 0.0, start_pos.y), Vector3(size.x, 0.0, size.y)));
-
PoolVector<Vector3> points;
PoolVector<Vector3> normals;
PoolVector<float> tangents;
@@ -924,7 +950,7 @@ void PlaneMesh::_bind_methods() {
void PlaneMesh::set_size(const Size2 &p_size) {
size = p_size;
- _queue_update();
+ _request_update();
}
Size2 PlaneMesh::get_size() const {
@@ -933,7 +959,7 @@ Size2 PlaneMesh::get_size() const {
void PlaneMesh::set_subdivide_width(const int p_subdivide) {
subdivide_w = p_subdivide > 0 ? p_subdivide : 0;
- _queue_update();
+ _request_update();
}
int PlaneMesh::get_subdivide_width() const {
@@ -942,7 +968,7 @@ int PlaneMesh::get_subdivide_width() const {
void PlaneMesh::set_subdivide_depth(const int p_subdivide) {
subdivide_d = p_subdivide > 0 ? p_subdivide : 0;
- _queue_update();
+ _request_update();
}
int PlaneMesh::get_subdivide_depth() const {
@@ -960,7 +986,7 @@ PlaneMesh::PlaneMesh() {
PrismMesh
*/
-void PrismMesh::_create_mesh_array(Array &p_arr) {
+void PrismMesh::_create_mesh_array(Array &p_arr) const {
int i, j, prevrow, thisrow, point;
float x, y, z;
float onethird = 1.0 / 3.0;
@@ -969,7 +995,6 @@ void PrismMesh::_create_mesh_array(Array &p_arr) {
Vector3 start_pos = size * -0.5;
// set our bounding box
- set_aabb(Rect3(start_pos, size));
PoolVector<Vector3> points;
PoolVector<Vector3> normals;
@@ -1196,7 +1221,7 @@ void PrismMesh::_bind_methods() {
void PrismMesh::set_left_to_right(const float p_left_to_right) {
left_to_right = p_left_to_right;
- _queue_update();
+ _request_update();
}
float PrismMesh::get_left_to_right() const {
@@ -1205,7 +1230,7 @@ float PrismMesh::get_left_to_right() const {
void PrismMesh::set_size(const Vector3 &p_size) {
size = p_size;
- _queue_update();
+ _request_update();
}
Vector3 PrismMesh::get_size() const {
@@ -1214,7 +1239,7 @@ Vector3 PrismMesh::get_size() const {
void PrismMesh::set_subdivide_width(const int p_divisions) {
subdivide_w = p_divisions > 0 ? p_divisions : 0;
- _queue_update();
+ _request_update();
}
int PrismMesh::get_subdivide_width() const {
@@ -1223,7 +1248,7 @@ int PrismMesh::get_subdivide_width() const {
void PrismMesh::set_subdivide_height(const int p_divisions) {
subdivide_h = p_divisions > 0 ? p_divisions : 0;
- _queue_update();
+ _request_update();
}
int PrismMesh::get_subdivide_height() const {
@@ -1232,7 +1257,7 @@ int PrismMesh::get_subdivide_height() const {
void PrismMesh::set_subdivide_depth(const int p_divisions) {
subdivide_d = p_divisions > 0 ? p_divisions : 0;
- _queue_update();
+ _request_update();
}
int PrismMesh::get_subdivide_depth() const {
@@ -1252,7 +1277,7 @@ PrismMesh::PrismMesh() {
QuadMesh
*/
-void QuadMesh::_create_mesh_array(Array &p_arr) {
+void QuadMesh::_create_mesh_array(Array &p_arr) const {
PoolVector<Vector3> faces;
PoolVector<Vector3> normals;
PoolVector<float> tangents;
@@ -1307,12 +1332,11 @@ QuadMesh::QuadMesh() {
SphereMesh
*/
-void SphereMesh::_create_mesh_array(Array &p_arr) {
+void SphereMesh::_create_mesh_array(Array &p_arr) const {
int i, j, prevrow, thisrow, point;
float x, y, z;
// set our bounding box
- set_aabb(Rect3(Vector3(-radius, height * -0.5, -radius), Vector3(radius * 2.0, height, radius * 2.0)));
PoolVector<Vector3> points;
PoolVector<Vector3> normals;
@@ -1401,7 +1425,7 @@ void SphereMesh::_bind_methods() {
void SphereMesh::set_radius(const float p_radius) {
radius = p_radius;
- _queue_update();
+ _request_update();
}
float SphereMesh::get_radius() const {
@@ -1410,7 +1434,7 @@ float SphereMesh::get_radius() const {
void SphereMesh::set_height(const float p_height) {
height = p_height;
- _queue_update();
+ _request_update();
}
float SphereMesh::get_height() const {
@@ -1419,7 +1443,7 @@ float SphereMesh::get_height() const {
void SphereMesh::set_radial_segments(const int p_radial_segments) {
radial_segments = p_radial_segments > 4 ? p_radial_segments : 4;
- _queue_update();
+ _request_update();
}
int SphereMesh::get_radial_segments() const {
@@ -1428,7 +1452,7 @@ int SphereMesh::get_radial_segments() const {
void SphereMesh::set_rings(const int p_rings) {
rings = p_rings > 1 ? p_rings : 1;
- _queue_update();
+ _request_update();
}
int SphereMesh::get_rings() const {
@@ -1437,7 +1461,7 @@ int SphereMesh::get_rings() const {
void SphereMesh::set_is_hemisphere(const bool p_is_hemisphere) {
is_hemisphere = p_is_hemisphere;
- _queue_update();
+ _request_update();
}
bool SphereMesh::get_is_hemisphere() const {
diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h
index 91d1af2ee1..bcd5d30dd3 100644
--- a/scene/resources/primitive_meshes.h
+++ b/scene/resources/primitive_meshes.h
@@ -47,22 +47,20 @@ class PrimitiveMesh : public Mesh {
private:
RID mesh;
- Rect3 aabb;
+ mutable Rect3 aabb;
Ref<Material> material;
- bool cache_is_dirty;
- void _update();
+ mutable bool pending_request;
+ void _update() const;
protected:
Mesh::PrimitiveType primitive_type;
static void _bind_methods();
- virtual void _create_mesh_array(Array &p_arr) = 0;
- void _queue_update();
-
- void set_aabb(Rect3 p_aabb);
+ virtual void _create_mesh_array(Array &p_arr) const = 0;
+ void _request_update();
public:
virtual int get_surface_count() const;
@@ -98,7 +96,7 @@ private:
protected:
static void _bind_methods();
- virtual void _create_mesh_array(Array &p_arr);
+ virtual void _create_mesh_array(Array &p_arr) const;
public:
void set_radius(const float p_radius);
@@ -131,7 +129,7 @@ private:
protected:
static void _bind_methods();
- virtual void _create_mesh_array(Array &p_arr);
+ virtual void _create_mesh_array(Array &p_arr) const;
public:
void set_size(const Vector3 &p_size);
@@ -166,7 +164,7 @@ private:
protected:
static void _bind_methods();
- virtual void _create_mesh_array(Array &p_arr);
+ virtual void _create_mesh_array(Array &p_arr) const;
public:
void set_top_radius(const float p_radius);
@@ -201,7 +199,7 @@ private:
protected:
static void _bind_methods();
- virtual void _create_mesh_array(Array &p_arr);
+ virtual void _create_mesh_array(Array &p_arr) const;
public:
void set_size(const Size2 &p_size);
@@ -232,7 +230,7 @@ private:
protected:
static void _bind_methods();
- virtual void _create_mesh_array(Array &p_arr);
+ virtual void _create_mesh_array(Array &p_arr) const;
public:
void set_left_to_right(const float p_left_to_right);
@@ -266,7 +264,7 @@ private:
protected:
static void _bind_methods();
- virtual void _create_mesh_array(Array &p_arr);
+ virtual void _create_mesh_array(Array &p_arr) const;
public:
QuadMesh();
@@ -288,7 +286,7 @@ private:
protected:
static void _bind_methods();
- virtual void _create_mesh_array(Array &p_arr);
+ virtual void _create_mesh_array(Array &p_arr) const;
public:
void set_radius(const float p_radius);
diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp
index 8ad2970005..03a862b744 100644
--- a/scene/resources/scene_format_text.cpp
+++ b/scene/resources/scene_format_text.cpp
@@ -29,8 +29,8 @@
/*************************************************************************/
#include "scene_format_text.h"
-#include "global_config.h"
#include "os/dir_access.h"
+#include "project_settings.h"
#include "version.h"
//version 2: changed names for basis, rect3, poolvectors, etc.
@@ -110,7 +110,7 @@ Error ResourceInteractiveLoaderText::_parse_ext_resource(VariantParser::Stream *
if (path.find("://") == -1 && path.is_rel_path()) {
// path is relative to file being loaded, so convert to a resource path
- path = GlobalConfig::get_singleton()->localize_path(res_path.get_base_dir().plus_file(path));
+ path = ProjectSettings::get_singleton()->localize_path(res_path.get_base_dir().plus_file(path));
}
r_res = ResourceLoader::load(path, type);
@@ -165,7 +165,7 @@ Error ResourceInteractiveLoaderText::poll() {
if (path.find("://") == -1 && path.is_rel_path()) {
// path is relative to file being loaded, so convert to a resource path
- path = GlobalConfig::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path));
+ path = ProjectSettings::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path));
}
if (remaps.has(path)) {
@@ -648,7 +648,7 @@ void ResourceInteractiveLoaderText::get_dependencies(FileAccess *f, List<String>
if (path.find("://") == -1 && path.is_rel_path()) {
// path is relative to file being loaded, so convert to a resource path
- path = GlobalConfig::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path));
+ path = ProjectSettings::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path));
}
if (p_add_types) {
@@ -905,9 +905,9 @@ Ref<ResourceInteractiveLoader> ResourceFormatLoaderText::load_interactive(const
}
Ref<ResourceInteractiveLoaderText> ria = memnew(ResourceInteractiveLoaderText);
- ria->local_path = GlobalConfig::get_singleton()->localize_path(p_path);
+ ria->local_path = ProjectSettings::get_singleton()->localize_path(p_path);
ria->res_path = ria->local_path;
- //ria->set_local_path( GlobalConfig::get_singleton()->localize_path(p_path) );
+ //ria->set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) );
ria->open(f);
return ria;
@@ -953,9 +953,9 @@ String ResourceFormatLoaderText::get_resource_type(const String &p_path) const {
}
Ref<ResourceInteractiveLoaderText> ria = memnew(ResourceInteractiveLoaderText);
- ria->local_path = GlobalConfig::get_singleton()->localize_path(p_path);
+ ria->local_path = ProjectSettings::get_singleton()->localize_path(p_path);
ria->res_path = ria->local_path;
- //ria->set_local_path( GlobalConfig::get_singleton()->localize_path(p_path) );
+ //ria->set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) );
String r = ria->recognize(f);
return r;
}
@@ -969,9 +969,9 @@ void ResourceFormatLoaderText::get_dependencies(const String &p_path, List<Strin
}
Ref<ResourceInteractiveLoaderText> ria = memnew(ResourceInteractiveLoaderText);
- ria->local_path = GlobalConfig::get_singleton()->localize_path(p_path);
+ ria->local_path = ProjectSettings::get_singleton()->localize_path(p_path);
ria->res_path = ria->local_path;
- //ria->set_local_path( GlobalConfig::get_singleton()->localize_path(p_path) );
+ //ria->set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) );
ria->get_dependencies(f, p_dependencies, p_add_types);
}
@@ -984,9 +984,9 @@ Error ResourceFormatLoaderText::rename_dependencies(const String &p_path, const
}
Ref<ResourceInteractiveLoaderText> ria = memnew(ResourceInteractiveLoaderText);
- ria->local_path = GlobalConfig::get_singleton()->localize_path(p_path);
+ ria->local_path = ProjectSettings::get_singleton()->localize_path(p_path);
ria->res_path = ria->local_path;
- //ria->set_local_path( GlobalConfig::get_singleton()->localize_path(p_path) );
+ //ria->set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) );
return ria->rename_dependencies(f, p_path, p_map);
}
@@ -1118,7 +1118,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r
ERR_FAIL_COND_V(err, ERR_CANT_OPEN);
FileAccessRef _fref(f);
- local_path = GlobalConfig::get_singleton()->localize_path(p_path);
+ local_path = ProjectSettings::get_singleton()->localize_path(p_path);
relative_paths = p_flags & ResourceSaver::FLAG_RELATIVE_PATHS;
skip_editor = p_flags & ResourceSaver::FLAG_OMIT_EDITOR_PROPERTIES;
diff --git a/scene/resources/sky_box.cpp b/scene/resources/sky_box.cpp
index 61aaaf8fb4..b1ca72571e 100644
--- a/scene/resources/sky_box.cpp
+++ b/scene/resources/sky_box.cpp
@@ -47,8 +47,11 @@ void Sky::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_radiance_size", "size"), &Sky::set_radiance_size);
ClassDB::bind_method(D_METHOD("get_radiance_size"), &Sky::get_radiance_size);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "radiance_size", PROPERTY_HINT_ENUM, "256,512,1024,2048"), "set_radiance_size", "get_radiance_size");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "radiance_size", PROPERTY_HINT_ENUM, "32,64,128,256,512,1024,2048"), "set_radiance_size", "get_radiance_size");
+ BIND_CONSTANT(RADIANCE_SIZE_32);
+ BIND_CONSTANT(RADIANCE_SIZE_64);
+ BIND_CONSTANT(RADIANCE_SIZE_128);
BIND_CONSTANT(RADIANCE_SIZE_256);
BIND_CONSTANT(RADIANCE_SIZE_512);
BIND_CONSTANT(RADIANCE_SIZE_1024);
@@ -66,7 +69,7 @@ void PanoramaSky::_radiance_changed() {
if (panorama.is_valid()) {
static const int size[RADIANCE_SIZE_MAX] = {
- 256, 512, 1024, 2048
+ 32, 64, 128, 256, 512, 1024, 2048
};
VS::get_singleton()->sky_set_texture(sky, panorama->get_rid(), size[get_radiance_size()]);
}
@@ -120,7 +123,7 @@ void ProceduralSky::_radiance_changed() {
return; //do nothing yet
static const int size[RADIANCE_SIZE_MAX] = {
- 256, 512, 1024, 2048
+ 32, 64, 128, 256, 512, 1024, 2048
};
VS::get_singleton()->sky_set_texture(sky, texture, size[get_radiance_size()]);
}
@@ -132,7 +135,7 @@ void ProceduralSky::_update_sky() {
PoolVector<uint8_t> imgdata;
static const int size[TEXTURE_SIZE_MAX] = {
- 1024, 2048, 4096
+ 256, 512, 1024, 2048, 4096
};
int w = size[texture_size];
@@ -465,7 +468,14 @@ void ProceduralSky::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_sun_energy", "get_sun_energy");
ADD_GROUP("Texture", "texture_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_size", PROPERTY_HINT_ENUM, "1024,2048,4096"), "set_texture_size", "get_texture_size");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_size", PROPERTY_HINT_ENUM, "256,512,1024,2048,4096"), "set_texture_size", "get_texture_size");
+
+ BIND_CONSTANT(TEXTURE_SIZE_256);
+ BIND_CONSTANT(TEXTURE_SIZE_512);
+ BIND_CONSTANT(TEXTURE_SIZE_1024);
+ BIND_CONSTANT(TEXTURE_SIZE_2048);
+ BIND_CONSTANT(TEXTURE_SIZE_4096);
+ BIND_CONSTANT(TEXTURE_SIZE_MAX);
}
ProceduralSky::ProceduralSky() {
@@ -474,15 +484,14 @@ ProceduralSky::ProceduralSky() {
texture = VS::get_singleton()->texture_create();
update_queued = false;
-
- sky_top_color = Color::hex(0x4d67e8ff);
+ sky_top_color = Color::hex(0x0c74f9ff);
sky_horizon_color = Color::hex(0x8ed2e8ff);
sky_curve = 0.25;
sky_energy = 1;
- ground_bottom_color = Color::hex(0x322719ff);
- ground_horizon_color = Color::hex(0x543610ff);
- ground_curve = 0.25;
+ ground_bottom_color = Color::hex(0x1a2530ff);
+ ground_horizon_color = Color::hex(0x7bc9f3ff);
+ ground_curve = 0.01;
ground_energy = 1;
sun_color = Color(1, 1, 1);
diff --git a/scene/resources/sky_box.h b/scene/resources/sky_box.h
index 7b707af3a6..8298d1b3c0 100644
--- a/scene/resources/sky_box.h
+++ b/scene/resources/sky_box.h
@@ -37,6 +37,9 @@ class Sky : public Resource {
public:
enum RadianceSize {
+ RADIANCE_SIZE_32,
+ RADIANCE_SIZE_64,
+ RADIANCE_SIZE_128,
RADIANCE_SIZE_256,
RADIANCE_SIZE_512,
RADIANCE_SIZE_1024,
@@ -85,6 +88,8 @@ class ProceduralSky : public Sky {
public:
enum TextureSize {
+ TEXTURE_SIZE_256,
+ TEXTURE_SIZE_512,
TEXTURE_SIZE_1024,
TEXTURE_SIZE_2048,
TEXTURE_SIZE_4096,
diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp
index c67f40782d..3666c18487 100644
--- a/scene/resources/style_box.cpp
+++ b/scene/resources/style_box.cpp
@@ -438,3 +438,81 @@ StyleBoxFlat::StyleBoxFlat() {
}
StyleBoxFlat::~StyleBoxFlat() {
}
+
+void StyleBoxLine::set_color(const Color &p_color) {
+ color = p_color;
+ emit_changed();
+}
+Color StyleBoxLine::get_color() const {
+ return color;
+}
+
+void StyleBoxLine::set_thickness(int p_thickness) {
+ thickness = p_thickness;
+ emit_changed();
+}
+int StyleBoxLine::get_thickness() const {
+ return thickness;
+}
+
+void StyleBoxLine::set_vertical(bool p_vertical) {
+ vertical = p_vertical;
+}
+bool StyleBoxLine::is_vertical() const {
+ return vertical;
+}
+
+void StyleBoxLine::set_grow(float p_grow) {
+ grow = p_grow;
+ emit_changed();
+}
+float StyleBoxLine::get_grow() const {
+ return grow;
+}
+
+void StyleBoxLine::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_color", "color"), &StyleBoxLine::set_color);
+ ClassDB::bind_method(D_METHOD("get_color"), &StyleBoxLine::get_color);
+ ClassDB::bind_method(D_METHOD("set_thickness", "thickness"), &StyleBoxLine::set_thickness);
+ ClassDB::bind_method(D_METHOD("get_thickness"), &StyleBoxLine::get_thickness);
+ ClassDB::bind_method(D_METHOD("set_grow", "grow"), &StyleBoxLine::set_grow);
+ ClassDB::bind_method(D_METHOD("get_grow"), &StyleBoxLine::get_grow);
+ ClassDB::bind_method(D_METHOD("set_vertical", "vertical"), &StyleBoxLine::set_vertical);
+ ClassDB::bind_method(D_METHOD("is_vertical"), &StyleBoxLine::is_vertical);
+
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "thickness", PROPERTY_HINT_RANGE, "0,10"), "set_thickness", "get_thickness");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vertical"), "set_vertical", "is_vertical");
+}
+float StyleBoxLine::get_style_margin(Margin p_margin) const {
+ return thickness;
+}
+Size2 StyleBoxLine::get_center_size() const {
+ return Size2();
+}
+
+void StyleBoxLine::draw(RID p_canvas_item, const Rect2 &p_rect) const {
+ VisualServer *vs = VisualServer::get_singleton();
+ Rect2i r = p_rect;
+
+ if (vertical) {
+ r.position.y -= grow;
+ r.size.y += grow * 2;
+ r.size.x = thickness;
+ } else {
+ r.position.x -= grow;
+ r.size.x += grow * 2;
+ r.size.y = thickness;
+ }
+
+ vs->canvas_item_add_rect(p_canvas_item, r, color);
+}
+
+StyleBoxLine::StyleBoxLine() {
+ grow = 1.0;
+ thickness = 1;
+ color = Color(0.0, 0.0, 0.0);
+ vertical = false;
+}
+StyleBoxLine::~StyleBoxLine() {}
diff --git a/scene/resources/style_box.h b/scene/resources/style_box.h
index 7547c2ea81..64ce3528aa 100644
--- a/scene/resources/style_box.h
+++ b/scene/resources/style_box.h
@@ -164,4 +164,38 @@ public:
~StyleBoxFlat();
};
+// just used to draw lines.
+class StyleBoxLine : public StyleBox {
+
+ GDCLASS(StyleBoxLine, StyleBox);
+ Color color;
+ int thickness;
+ bool vertical;
+ float grow;
+
+protected:
+ virtual float get_style_margin(Margin p_margin) const;
+ static void _bind_methods();
+
+public:
+ void set_color(const Color &p_color);
+ Color get_color() const;
+
+ void set_thickness(int p_thickness);
+ int get_thickness() const;
+
+ void set_vertical(bool p_vertical);
+ bool is_vertical() const;
+
+ void set_grow(float p_grow);
+ float get_grow() const;
+
+ virtual Size2 get_center_size() const;
+
+ virtual void draw(RID p_canvas_item, const Rect2 &p_rect) const;
+
+ StyleBoxLine();
+ ~StyleBoxLine();
+};
+
#endif
diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp
index b2822ca0c4..8478432a04 100644
--- a/scene/resources/surface_tool.cpp
+++ b/scene/resources/surface_tool.cpp
@@ -812,11 +812,13 @@ void SurfaceTool::clear() {
index_array.clear();
vertex_array.clear();
smooth_groups.clear();
+ material.unref();
}
void SurfaceTool::_bind_methods() {
ClassDB::bind_method(D_METHOD("begin", "primitive"), &SurfaceTool::begin);
+
ClassDB::bind_method(D_METHOD("add_vertex", "vertex"), &SurfaceTool::add_vertex);
ClassDB::bind_method(D_METHOD("add_color", "color"), &SurfaceTool::add_color);
ClassDB::bind_method(D_METHOD("add_normal", "normal"), &SurfaceTool::add_normal);
@@ -826,15 +828,25 @@ void SurfaceTool::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_bones", "bones"), &SurfaceTool::add_bones);
ClassDB::bind_method(D_METHOD("add_weights", "weights"), &SurfaceTool::add_weights);
ClassDB::bind_method(D_METHOD("add_smooth_group", "smooth"), &SurfaceTool::add_smooth_group);
+
ClassDB::bind_method(D_METHOD("add_triangle_fan", "vertexes", "uvs", "colors", "uv2s", "normals", "tangents"), &SurfaceTool::add_triangle_fan, DEFVAL(Vector<Vector2>()), DEFVAL(Vector<Color>()), DEFVAL(Vector<Vector2>()), DEFVAL(Vector<Vector3>()), DEFVAL(Vector<Plane>()));
- ClassDB::bind_method(D_METHOD("set_material", "material:Material"), &SurfaceTool::set_material);
+
+ ClassDB::bind_method(D_METHOD("add_index", "index"), &SurfaceTool::add_index);
+
ClassDB::bind_method(D_METHOD("index"), &SurfaceTool::index);
ClassDB::bind_method(D_METHOD("deindex"), &SurfaceTool::deindex);
- ///ClassDB::bind_method(D_METHOD("generate_flat_normals"),&SurfaceTool::generate_flat_normals);
ClassDB::bind_method(D_METHOD("generate_normals"), &SurfaceTool::generate_normals);
- ClassDB::bind_method(D_METHOD("add_index", "index"), &SurfaceTool::add_index);
- ClassDB::bind_method(D_METHOD("commit:Mesh", "existing:Mesh"), &SurfaceTool::commit, DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("generate_tangents"), &SurfaceTool::generate_tangents);
+
+ ClassDB::bind_method(D_METHOD("add_to_format", "flags"), &SurfaceTool::add_to_format);
+
+ ClassDB::bind_method(D_METHOD("set_material", "material:Material"), &SurfaceTool::set_material);
+
ClassDB::bind_method(D_METHOD("clear"), &SurfaceTool::clear);
+
+ ClassDB::bind_method(D_METHOD("create_from", "existing:Mesh", "surface"), &SurfaceTool::create_from);
+ ClassDB::bind_method(D_METHOD("append_from", "existing:Mesh", "surface", "transform"), &SurfaceTool::append_from);
+ ClassDB::bind_method(D_METHOD("commit:Mesh", "existing:Mesh"), &SurfaceTool::commit, DEFVAL(Variant()));
}
SurfaceTool::SurfaceTool() {
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index f6856b3539..fe7cd0097c 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -1327,8 +1327,8 @@ void CubeMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_flags", "flags"), &CubeMap::set_flags);
ClassDB::bind_method(D_METHOD("get_flags"), &CubeMap::get_flags);
- ClassDB::bind_method(D_METHOD("set_side", "side", "image"), &CubeMap::set_side);
- ClassDB::bind_method(D_METHOD("get_side", "side"), &CubeMap::get_side);
+ ClassDB::bind_method(D_METHOD("set_side", "side", "image:Image"), &CubeMap::set_side);
+ ClassDB::bind_method(D_METHOD("get_side:Image", "side"), &CubeMap::get_side);
ClassDB::bind_method(D_METHOD("set_storage", "mode"), &CubeMap::set_storage);
ClassDB::bind_method(D_METHOD("get_storage"), &CubeMap::get_storage);
ClassDB::bind_method(D_METHOD("set_lossy_storage_quality", "quality"), &CubeMap::set_lossy_storage_quality);
diff --git a/scene/resources/texture.h b/scene/resources/texture.h
index 9bbbd1d091..6c20c71af0 100644
--- a/scene/resources/texture.h
+++ b/scene/resources/texture.h
@@ -414,7 +414,7 @@ public:
void set_width(int p_width);
int get_width() const;
- void ensure_default_setup(float p_min=0, float p_max=1);
+ void ensure_default_setup(float p_min = 0, float p_max = 1);
void set_curve(Ref<Curve> p_curve);
Ref<Curve> get_curve() const;
diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp
index faf9f31b43..d5c68457d0 100644
--- a/scene/resources/theme.cpp
+++ b/scene/resources/theme.cpp
@@ -660,8 +660,8 @@ void Theme::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear_constant", "name", "type"), &Theme::clear_constant);
ClassDB::bind_method(D_METHOD("get_constant_list", "type"), &Theme::_get_constant_list);
- ClassDB::bind_method(D_METHOD("set_default_font", "font"), &Theme::set_default_theme_font);
- ClassDB::bind_method(D_METHOD("get_default_font"), &Theme::get_default_theme_font);
+ ClassDB::bind_method(D_METHOD("set_default_font", "font:Font"), &Theme::set_default_theme_font);
+ ClassDB::bind_method(D_METHOD("get_default_font:Font"), &Theme::get_default_theme_font);
ClassDB::bind_method(D_METHOD("get_type_list", "type"), &Theme::_get_type_list);
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index b9d2c503e1..dc8f6a0a69 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -57,8 +57,12 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
tile_set_region(id, p_value);
else if (what == "shape")
tile_set_shape(id, 0, p_value);
- else if (what == "shape_offset")
- tile_set_shape_offset(id, 0, p_value);
+ else if (what == "shape_offset") {
+ Transform2D xform = tile_get_shape_transform(id, 0);
+ xform.set_origin(p_value);
+ tile_set_shape_transform(id, 0, xform);
+ } else if (what == "shape_transform")
+ tile_set_shape_transform(id, 0, p_value);
else if (what == "shape_one_way")
tile_set_shape_one_way(id, 0, p_value);
else if (what == "shapes")
@@ -106,7 +110,9 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const {
else if (what == "shape")
r_ret = tile_get_shape(id, 0);
else if (what == "shape_offset")
- r_ret = tile_get_shape_offset(id, 0);
+ r_ret = tile_get_shape_transform(id, 0).get_origin();
+ else if (what == "shape_transform")
+ r_ret = tile_get_shape_transform(id, 0);
else if (what == "shape_one_way")
r_ret = tile_get_shape_one_way(id, 0);
else if (what == "shapes")
@@ -143,6 +149,7 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const {
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::ARRAY, pre + "shapes", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
@@ -252,13 +259,13 @@ void TileSet::tile_clear_shapes(int p_id) {
tile_map[p_id].shapes_data.clear();
}
-void TileSet::tile_add_shape(int p_id, const Ref<Shape2D> &p_shape, const Vector2 &p_offset, bool p_one_way) {
+void TileSet::tile_add_shape(int p_id, const Ref<Shape2D> &p_shape, const Transform2D &p_transform, bool p_one_way) {
ERR_FAIL_COND(!tile_map.has(p_id));
ShapeData new_data = ShapeData();
new_data.shape = p_shape;
- new_data.shape_offset = p_offset;
+ new_data.shape_transform = p_transform;
new_data.one_way_collision = p_one_way;
tile_map[p_id].shapes_data.push_back(new_data);
@@ -288,22 +295,22 @@ Ref<Shape2D> TileSet::tile_get_shape(int p_id, int p_shape_id) const {
return Ref<Shape2D>();
}
-void TileSet::tile_set_shape_offset(int p_id, int p_shape_id, const Vector2 &p_offset) {
+void TileSet::tile_set_shape_transform(int p_id, int p_shape_id, const Transform2D &p_offset) {
ERR_FAIL_COND(!tile_map.has(p_id));
if (tile_map[p_id].shapes_data.size() <= p_shape_id)
tile_map[p_id].shapes_data.resize(p_shape_id + 1);
- tile_map[p_id].shapes_data[p_shape_id].shape_offset = p_offset;
+ tile_map[p_id].shapes_data[p_shape_id].shape_transform = p_offset;
emit_changed();
}
-Vector2 TileSet::tile_get_shape_offset(int p_id, int p_shape_id) const {
+Transform2D TileSet::tile_get_shape_transform(int p_id, int p_shape_id) const {
- ERR_FAIL_COND_V(!tile_map.has(p_id), Vector2());
+ ERR_FAIL_COND_V(!tile_map.has(p_id), Transform2D());
if (tile_map[p_id].shapes_data.size() > p_shape_id)
- return tile_map[p_id].shapes_data[p_shape_id].shape_offset;
+ return tile_map[p_id].shapes_data[p_shape_id].shape_transform;
- return Vector2();
+ return Transform2D();
}
void TileSet::tile_set_shape_one_way(int p_id, int p_shape_id, const bool p_one_way) {
@@ -388,7 +395,7 @@ void TileSet::_tile_set_shapes(int p_id, const Array &p_shapes) {
ERR_FAIL_COND(!tile_map.has(p_id));
Vector<ShapeData> shapes_data;
- Vector2 default_offset = tile_get_shape_offset(p_id, 0);
+ Transform2D default_transform = tile_get_shape_transform(p_id, 0);
bool default_one_way = tile_get_shape_one_way(p_id, 0);
for (int i = 0; i < p_shapes.size(); i++) {
ShapeData s = ShapeData();
@@ -398,7 +405,7 @@ void TileSet::_tile_set_shapes(int p_id, const Array &p_shapes) {
if (shape.is_null()) continue;
s.shape = shape;
- s.shape_offset = default_offset;
+ s.shape_transform = default_transform;
s.one_way_collision = default_one_way;
} else if (p_shapes[i].get_type() == Variant::DICTIONARY) {
Dictionary d = p_shapes[i];
@@ -408,10 +415,12 @@ void TileSet::_tile_set_shapes(int p_id, const Array &p_shapes) {
else
continue;
- if (d.has("shape_offset") && d["shape_offset"].get_type() == Variant::VECTOR2)
- s.shape_offset = d["shape_offset"];
+ if (d.has("shape_transform") && d["shape_transform"].get_type() == Variant::TRANSFORM2D)
+ s.shape_transform = d["shape_transform"];
+ else if (d.has("shape_offset") && d["shape_offset"].get_type() == Variant::VECTOR2)
+ s.shape_transform = Transform2D(0, (Vector2)d["shape_offset"]);
else
- s.shape_offset = default_offset;
+ s.shape_transform = default_transform;
if (d.has("one_way") && d["one_way"].get_type() == Variant::BOOL)
s.one_way_collision = d["one_way"];
@@ -438,7 +447,7 @@ Array TileSet::_tile_get_shapes(int p_id) const {
for (int i = 0; i < data.size(); i++) {
Dictionary shape_data;
shape_data["shape"] = data[i].shape;
- shape_data["shape_offset"] = data[i].shape_offset;
+ shape_data["shape_transform"] = data[i].shape_transform;
shape_data["one_way"] = data[i].one_way_collision;
arr.push_back(shape_data);
}
@@ -520,11 +529,11 @@ void TileSet::_bind_methods() {
ClassDB::bind_method(D_METHOD("tile_get_region", "id"), &TileSet::tile_get_region);
ClassDB::bind_method(D_METHOD("tile_set_shape", "id", "shape_id", "shape:Shape2D"), &TileSet::tile_set_shape);
ClassDB::bind_method(D_METHOD("tile_get_shape:Shape2D", "id", "shape_id"), &TileSet::tile_get_shape);
- ClassDB::bind_method(D_METHOD("tile_set_shape_offset", "id", "shape_id", "shape_offset"), &TileSet::tile_set_shape_offset);
- ClassDB::bind_method(D_METHOD("tile_get_shape_offset", "id", "shape_id"), &TileSet::tile_get_shape_offset);
+ ClassDB::bind_method(D_METHOD("tile_set_shape_transform", "id", "shape_id", "shape_transform"), &TileSet::tile_set_shape_transform);
+ ClassDB::bind_method(D_METHOD("tile_get_shape_transform", "id", "shape_id"), &TileSet::tile_get_shape_transform);
ClassDB::bind_method(D_METHOD("tile_set_shape_one_way", "id", "shape_id", "one_way"), &TileSet::tile_set_shape_one_way);
ClassDB::bind_method(D_METHOD("tile_get_shape_one_way", "id", "shape_id"), &TileSet::tile_get_shape_one_way);
- ClassDB::bind_method(D_METHOD("tile_add_shape", "id", "shape:Shape2D", "shape_offset", "one_way"), &TileSet::tile_add_shape, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("tile_add_shape", "id", "shape:Shape2D", "shape_transform", "one_way"), &TileSet::tile_add_shape, DEFVAL(false));
ClassDB::bind_method(D_METHOD("tile_get_shape_count", "id"), &TileSet::tile_get_shape_count);
ClassDB::bind_method(D_METHOD("tile_set_shapes", "id", "shapes"), &TileSet::_tile_set_shapes);
ClassDB::bind_method(D_METHOD("tile_get_shapes", "id"), &TileSet::_tile_get_shapes);
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index c07d82c75a..99c506390c 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -43,7 +43,7 @@ class TileSet : public Resource {
public:
struct ShapeData {
Ref<Shape2D> shape;
- Vector2 shape_offset;
+ Transform2D shape_transform;
bool one_way_collision;
ShapeData() {
@@ -105,14 +105,14 @@ public:
void tile_set_shape(int p_id, int p_shape_id, const Ref<Shape2D> &p_shape);
Ref<Shape2D> tile_get_shape(int p_id, int p_shape_id) const;
- void tile_set_shape_offset(int p_id, int p_shape_id, const Vector2 &p_offset);
- Vector2 tile_get_shape_offset(int p_id, int p_shape_id) const;
+ void tile_set_shape_transform(int p_id, int p_shape_id, const Transform2D &p_transform);
+ Transform2D tile_get_shape_transform(int p_id, int p_shape_id) const;
void tile_set_shape_one_way(int p_id, int p_shape_id, bool p_one_way);
bool tile_get_shape_one_way(int p_id, int p_shape_id) const;
void tile_clear_shapes(int p_id);
- void tile_add_shape(int p_id, const Ref<Shape2D> &p_shape, const Vector2 &p_offset, bool p_one_way = false);
+ void tile_add_shape(int p_id, const Ref<Shape2D> &p_shape, const Transform2D &p_transform, bool p_one_way = false);
int tile_get_shape_count(int p_id) const;
void tile_set_shapes(int p_id, const Vector<ShapeData> &p_shapes);
diff --git a/scene/resources/world.cpp b/scene/resources/world.cpp
index 24551e9135..b84cc9563e 100644
--- a/scene/resources/world.cpp
+++ b/scene/resources/world.cpp
@@ -299,6 +299,13 @@ PhysicsDirectSpaceState *World::get_direct_space_state() {
return PhysicsServer::get_singleton()->space_get_direct_state(space);
}
+void World::get_camera_list(List<Camera *> *r_cameras) {
+
+ for (Map<Camera *, SpatialIndexer::CameraData>::Element *E = indexer->cameras.front(); E; E = E->next()) {
+ r_cameras->push_back(E->key());
+ }
+}
+
void World::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_space"), &World::get_space);
diff --git a/scene/resources/world.h b/scene/resources/world.h
index 5291b3974b..158086974c 100644
--- a/scene/resources/world.h
+++ b/scene/resources/world.h
@@ -76,6 +76,8 @@ public:
void set_fallback_environment(const Ref<Environment> &p_environment);
Ref<Environment> get_fallback_environment() const;
+ void get_camera_list(List<Camera *> *r_cameras);
+
PhysicsDirectSpaceState *get_direct_space_state();
World();
diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp
index 36d2a38b3d..056c49f1ae 100644
--- a/scene/resources/world_2d.cpp
+++ b/scene/resources/world_2d.cpp
@@ -31,8 +31,7 @@
#include "servers/physics_2d_server.h"
#include "servers/visual_server.h"
//#include "servers/spatial_sound_2d_server.h"
-#include "global_config.h"
-#include "global_config.h"
+#include "project_settings.h"
#include "scene/2d/camera_2d.h"
#include "scene/2d/visibility_notifier_2d.h"
#include "scene/main/viewport.h"
diff --git a/scene/resources/world_2d.h b/scene/resources/world_2d.h
index 35c8ce390f..f968b08a15 100644
--- a/scene/resources/world_2d.h
+++ b/scene/resources/world_2d.h
@@ -30,7 +30,7 @@
#ifndef WORLD_2D_H
#define WORLD_2D_H
-#include "global_config.h"
+#include "project_settings.h"
#include "resource.h"
#include "servers/physics_2d_server.h"