diff options
Diffstat (limited to 'scene')
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(¤t.filter, false); + current.filter_process[k * 2 + 1].set_filter(¤t.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(¤t.filter); + current.filter_process[k * 2 + 1].set_filter(¤t.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 Binary files differnew file mode 100644 index 0000000000..0d75182b8f --- /dev/null +++ b/scene/resources/default_theme/hslider_grabber_disabled.png 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 Binary files differnew file mode 100644 index 0000000000..c830359f45 --- /dev/null +++ b/scene/resources/default_theme/vslider_grabber_disabled.png 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" |