diff options
Diffstat (limited to 'scene')
79 files changed, 1100 insertions, 566 deletions
diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp index c062a6d1fc..73774e12d9 100644 --- a/scene/2d/animated_sprite.cpp +++ b/scene/2d/animated_sprite.cpp @@ -318,7 +318,7 @@ void AnimatedSprite::_validate_property(PropertyInfo& property) const { if (property.name=="frame") { - property.hint=PROPERTY_HINT_RANGE; + property.hint=PROPERTY_HINT_SPRITE_FRAME; if (frames->has_animation(animation)) { property.hint_string="0,"+itos(frames->get_frame_count(animation)-1)+",1"; diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index 85256be940..f98a50e3e0 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -44,7 +44,6 @@ void Camera2D::_update_scroll() { if (current) { Matrix32 xform = get_camera_transform(); - RID vp = viewport->get_viewport(); if (viewport) { viewport->set_canvas_transform( xform ); } @@ -409,6 +408,35 @@ void Camera2D::force_update_scroll() { _update_scroll(); } +void Camera2D::reset_smoothing() { + + smoothed_camera_pos = camera_pos; + _update_scroll(); +} + +void Camera2D::align() { + + Size2 screen_size = get_viewport_rect().size; + screen_size=get_viewport_rect().size; + Point2 current_camera_pos = get_global_transform().get_origin(); + if (anchor_mode==ANCHOR_MODE_DRAG_CENTER) { + if (h_ofs<0) { + camera_pos.x = current_camera_pos.x + screen_size.x * 0.5 * drag_margin[MARGIN_RIGHT] * h_ofs; + } else { + camera_pos.x = current_camera_pos.x + screen_size.x * 0.5 * drag_margin[MARGIN_LEFT] * h_ofs; + } + if (v_ofs<0) { + camera_pos.y = current_camera_pos.y + screen_size.y * 0.5 * drag_margin[MARGIN_TOP] * v_ofs; + } else { + camera_pos.y = current_camera_pos.y + screen_size.y * 0.5 * drag_margin[MARGIN_BOTTOM] * v_ofs; + } + } else if (anchor_mode==ANCHOR_MODE_FIXED_TOP_LEFT){ + + camera_pos=current_camera_pos; + } + + _update_scroll(); +} void Camera2D::set_follow_smoothing(float p_speed) { @@ -544,6 +572,8 @@ void Camera2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("is_follow_smoothing_enabled"),&Camera2D::is_follow_smoothing_enabled); ObjectTypeDB::bind_method(_MD("force_update_scroll"),&Camera2D::force_update_scroll); + ObjectTypeDB::bind_method(_MD("reset_smoothing"),&Camera2D::reset_smoothing); + ObjectTypeDB::bind_method(_MD("align"),&Camera2D::align); ObjectTypeDB::bind_method(_MD("_set_old_smoothing","follow_smoothing"),&Camera2D::_set_old_smoothing); diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h index 22e5bc382a..b3f55d798d 100644 --- a/scene/2d/camera_2d.h +++ b/scene/2d/camera_2d.h @@ -128,6 +128,8 @@ public: Vector2 get_camera_pos() const; void force_update_scroll(); + void reset_smoothing(); + void align(); Camera2D(); }; diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index 21a3ecef32..eb4f457975 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -948,67 +948,22 @@ Ref<CanvasItemMaterial> CanvasItem::get_material() const{ return material; } +Vector2 CanvasItem::make_canvas_pos_local(const Vector2& screen_point) const { -InputEvent CanvasItem::make_input_local(const InputEvent& p_event) const { - - ERR_FAIL_COND_V(!is_inside_tree(),p_event); - - InputEvent ev = p_event; - - Matrix32 local_matrix = (get_canvas_transform() * get_global_transform()).affine_inverse(); - - switch(ev.type) { - - case InputEvent::MOUSE_BUTTON: { - - Vector2 g = local_matrix.xform(Vector2(ev.mouse_button.global_x,ev.mouse_button.global_y)); - Vector2 l = local_matrix.xform(Vector2(ev.mouse_button.x,ev.mouse_button.y)); - ev.mouse_button.x=l.x; - ev.mouse_button.y=l.y; - ev.mouse_button.global_x=g.x; - ev.mouse_button.global_y=g.y; + ERR_FAIL_COND_V(!is_inside_tree(),screen_point); - } break; - case InputEvent::MOUSE_MOTION: { - - Vector2 g = local_matrix.xform(Vector2(ev.mouse_motion.global_x,ev.mouse_motion.global_y)); - Vector2 l = local_matrix.xform(Vector2(ev.mouse_motion.x,ev.mouse_motion.y)); - Vector2 r = local_matrix.basis_xform(Vector2(ev.mouse_motion.relative_x,ev.mouse_motion.relative_y)); - Vector2 s = local_matrix.basis_xform(Vector2(ev.mouse_motion.speed_x,ev.mouse_motion.speed_y)); - ev.mouse_motion.x=l.x; - ev.mouse_motion.y=l.y; - ev.mouse_motion.global_x=g.x; - ev.mouse_motion.global_y=g.y; - ev.mouse_motion.relative_x=r.x; - ev.mouse_motion.relative_y=r.y; - ev.mouse_motion.speed_x=s.x; - ev.mouse_motion.speed_y=s.y; + Matrix32 local_matrix = (get_canvas_transform() * + get_global_transform()).affine_inverse(); - } break; - case InputEvent::SCREEN_TOUCH: { + return local_matrix.xform(screen_point); +} +InputEvent CanvasItem::make_input_local(const InputEvent& p_event) const { - Vector2 t = local_matrix.xform(Vector2(ev.screen_touch.x,ev.screen_touch.y)); - ev.screen_touch.x=t.x; - ev.screen_touch.y=t.y; + ERR_FAIL_COND_V(!is_inside_tree(),p_event); - } break; - case InputEvent::SCREEN_DRAG: { - - - Vector2 t = local_matrix.xform(Vector2(ev.screen_drag.x,ev.screen_drag.y)); - Vector2 r = local_matrix.basis_xform(Vector2(ev.screen_drag.relative_x,ev.screen_drag.relative_y)); - Vector2 s = local_matrix.basis_xform(Vector2(ev.screen_drag.speed_x,ev.screen_drag.speed_y)); - ev.screen_drag.x=t.x; - ev.screen_drag.y=t.y; - ev.screen_drag.relative_x=r.x; - ev.screen_drag.relative_y=r.y; - ev.screen_drag.speed_x=s.x; - ev.screen_drag.speed_y=s.y; - } break; - } + return p_event.xform_by( (get_canvas_transform() * get_global_transform()).affine_inverse() ); - return ev; } @@ -1106,6 +1061,8 @@ void CanvasItem::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_use_parent_material","enable"),&CanvasItem::set_use_parent_material); ObjectTypeDB::bind_method(_MD("get_use_parent_material"),&CanvasItem::get_use_parent_material); + ObjectTypeDB::bind_method(_MD("make_canvas_pos_local","screen_point"), + &CanvasItem::make_canvas_pos_local); ObjectTypeDB::bind_method(_MD("make_input_local","event"),&CanvasItem::make_input_local); BIND_VMETHOD(MethodInfo("_draw")); diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index 8a61b449fd..b894310ce2 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -263,6 +263,7 @@ public: bool get_use_parent_material() const; InputEvent make_input_local(const InputEvent& pevent) const; + Vector2 make_canvas_pos_local(const Vector2& screen_point) const; Vector2 get_global_mouse_pos() const; Vector2 get_local_mouse_pos() const; diff --git a/scene/2d/navigation2d.cpp b/scene/2d/navigation2d.cpp index b4332cc75d..82c1327a8f 100644 --- a/scene/2d/navigation2d.cpp +++ b/scene/2d/navigation2d.cpp @@ -552,7 +552,6 @@ debug path if (p_optimize) { //string pulling - Polygon *apex_poly=end_poly; Vector2 apex_point=end_point; Vector2 portal_left=apex_point; Vector2 portal_right=apex_point; @@ -613,12 +612,9 @@ debug path //print_line("***ADVANCE LEFT"); } else { - //_clip_path(path,apex_poly,portal_right,right_poly); - apex_point=portal_right; p=right_poly; left_poly=p; - apex_poly=p; portal_left=apex_point; portal_right=apex_point; if (path[path.size()-1].distance_to(apex_point)>CMP_EPSILON) @@ -637,12 +633,9 @@ debug path //print_line("***ADVANCE RIGHT"); } else { - //_clip_path(path,apex_poly,portal_left,left_poly); - apex_point=portal_left; p=left_poly; right_poly=p; - apex_poly=p; portal_right=apex_point; portal_left=apex_point; if (path[path.size()-1].distance_to(apex_point)>CMP_EPSILON) diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp index 27aa08ec5b..c5b338bf59 100644 --- a/scene/2d/sprite.cpp +++ b/scene/2d/sprite.cpp @@ -288,6 +288,17 @@ Rect2 Sprite::get_item_rect() const { } + +void Sprite::_validate_property(PropertyInfo& property) const { + + if (property.name=="frame") { + + property.hint=PROPERTY_HINT_SPRITE_FRAME; + + property.hint_string="0,"+itos(vframes*hframes-1)+",1"; + } +} + void Sprite::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_texture","texture:Texture"),&Sprite::set_texture); diff --git a/scene/2d/sprite.h b/scene/2d/sprite.h index f789538b1d..32d3f476d1 100644 --- a/scene/2d/sprite.h +++ b/scene/2d/sprite.h @@ -61,6 +61,8 @@ protected: static void _bind_methods();; + virtual void _validate_property(PropertyInfo& property) const; + public: virtual void edit_set_pivot(const Point2& p_pivot); diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 1f16b36466..1a4f88c30e 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -222,6 +222,10 @@ void TileMap::_fix_cell_transform(Matrix32& xform,const Cell& p_cell, const Vect Size2 s=p_sc; Vector2 offset = p_offset; + + if (tile_origin==TILE_ORIGIN_BOTTOM_LEFT) + offset.y+=cell_size.y; + if (s.y > s.x) { if ((p_cell.flip_h && (p_cell.flip_v || p_cell.transpose)) || (p_cell.flip_v && !p_cell.transpose)) @@ -240,7 +244,7 @@ void TileMap::_fix_cell_transform(Matrix32& xform,const Cell& p_cell, const Vect if (p_cell.flip_h) { xform.elements[0].x=-xform.elements[0].x; xform.elements[1].x=-xform.elements[1].x; - if (tile_origin==TILE_ORIGIN_TOP_LEFT) + if (tile_origin==TILE_ORIGIN_TOP_LEFT || tile_origin==TILE_ORIGIN_BOTTOM_LEFT) offset.x=s.x-offset.x; } if (p_cell.flip_v) { @@ -248,6 +252,12 @@ void TileMap::_fix_cell_transform(Matrix32& xform,const Cell& p_cell, const Vect xform.elements[1].y=-xform.elements[1].y; if (tile_origin==TILE_ORIGIN_TOP_LEFT) offset.y=s.y-offset.y; + else if (tile_origin==TILE_ORIGIN_BOTTOM_LEFT) { + if(p_cell.transpose) + offset.y+=s.y; + else + offset.y-=s.y; + } } xform.elements[2].x+=offset.x; xform.elements[2].y+=offset.y; @@ -411,6 +421,24 @@ void TileMap::_update_dirty_quadrants() { if (tile_origin==TILE_ORIGIN_TOP_LEFT) { rect.pos+=tile_ofs; + + } else if (tile_origin==TILE_ORIGIN_BOTTOM_LEFT) { + + rect.pos+=tile_ofs; + + if(c.transpose) + { + if(c.flip_h) + rect.pos.x-=cell_size.x; + else + rect.pos.x+=cell_size.x; + } else { + if(c.flip_v) + rect.pos.y-=cell_size.y; + else + rect.pos.y+=cell_size.y; + } + } else if (tile_origin==TILE_ORIGIN_CENTER) { rect.pos+=tcenter; @@ -584,6 +612,9 @@ Map<TileMap::PosKey,TileMap::Quadrant>::Element *TileMap::_create_quadrant(const q.pos+=get_cell_draw_offset(); if (tile_origin==TILE_ORIGIN_CENTER) q.pos+=cell_size/2; + else if (tile_origin==TILE_ORIGIN_BOTTOM_LEFT) + q.pos.y+=cell_size.y; + xform.set_origin( q.pos ); // q.canvas_item = VisualServer::get_singleton()->canvas_item_create(); @@ -1242,7 +1273,7 @@ void TileMap::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::INT,"cell/quadrant_size",PROPERTY_HINT_RANGE,"1,128,1"),_SCS("set_quadrant_size"),_SCS("get_quadrant_size")); ADD_PROPERTY( PropertyInfo(Variant::MATRIX32,"cell/custom_transform"),_SCS("set_custom_transform"),_SCS("get_custom_transform")); ADD_PROPERTY( PropertyInfo(Variant::INT,"cell/half_offset",PROPERTY_HINT_ENUM,"Offset X,Offset Y,Disabled"),_SCS("set_half_offset"),_SCS("get_half_offset")); - ADD_PROPERTY( PropertyInfo(Variant::INT,"cell/tile_origin",PROPERTY_HINT_ENUM,"Top Left,Center"),_SCS("set_tile_origin"),_SCS("get_tile_origin")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"cell/tile_origin",PROPERTY_HINT_ENUM,"Top Left,Center,Bottom Left"),_SCS("set_tile_origin"),_SCS("get_tile_origin")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"cell/y_sort"),_SCS("set_y_sort_mode"),_SCS("is_y_sort_mode_enabled")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collision/use_kinematic",PROPERTY_HINT_NONE,""),_SCS("set_collision_use_kinematic"),_SCS("get_collision_use_kinematic")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_collision_friction"),_SCS("get_collision_friction")); @@ -1264,6 +1295,7 @@ void TileMap::_bind_methods() { BIND_CONSTANT( HALF_OFFSET_DISABLED ); BIND_CONSTANT( TILE_ORIGIN_TOP_LEFT ); BIND_CONSTANT( TILE_ORIGIN_CENTER ); + BIND_CONSTANT( TILE_ORIGIN_BOTTOM_LEFT ); } diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index cec5ac0a1b..b48fdde43f 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -54,7 +54,8 @@ public: enum TileOrigin { TILE_ORIGIN_TOP_LEFT, - TILE_ORIGIN_CENTER + TILE_ORIGIN_CENTER, + TILE_ORIGIN_BOTTOM_LEFT }; diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp index 12524a2192..5411950976 100644 --- a/scene/2d/visibility_notifier_2d.cpp +++ b/scene/2d/visibility_notifier_2d.cpp @@ -270,9 +270,6 @@ void VisibilityEnabler2D::_notification(int p_what){ return; - Node *from = this; - //find where current scene starts - for (Map<Node*,Variant>::Element *E=nodes.front();E;E=E->next()) { if (!visible) @@ -293,14 +290,7 @@ void VisibilityEnabler2D::_change_node_state(Node* p_node,bool p_enabled) { RigidBody2D *rb = p_node->cast_to<RigidBody2D>(); if (rb) { - if (p_enabled) { - RigidBody2D::Mode mode = RigidBody2D::Mode(nodes[p_node].operator int()); - //rb->set_mode(mode); - rb->set_sleeping(false); - } else { - //rb->set_mode(RigidBody2D::MODE_STATIC); - rb->set_sleeping(true); - } + rb->set_sleeping(!p_enabled); } } diff --git a/scene/3d/immediate_geometry.cpp b/scene/3d/immediate_geometry.cpp index 4964582be4..e83fa69b4f 100644 --- a/scene/3d/immediate_geometry.cpp +++ b/scene/3d/immediate_geometry.cpp @@ -149,7 +149,7 @@ void ImmediateGeometry::add_sphere(int p_lats,int p_lons,float p_radius) { void ImmediateGeometry::_bind_methods() { - ObjectTypeDB::bind_method(_MD("begin","primitive","texture:Texture"),&ImmediateGeometry::begin); + ObjectTypeDB::bind_method(_MD("begin","primitive","texture:Texture"),&ImmediateGeometry::begin,DEFVAL(Ref<Texture>())); ObjectTypeDB::bind_method(_MD("set_normal","normal"),&ImmediateGeometry::set_normal); ObjectTypeDB::bind_method(_MD("set_tangent","tangent"),&ImmediateGeometry::set_tangent); ObjectTypeDB::bind_method(_MD("set_color","color"),&ImmediateGeometry::set_color); diff --git a/scene/3d/immediate_geometry.h b/scene/3d/immediate_geometry.h index 28b5735ca8..c1cc4f87d5 100644 --- a/scene/3d/immediate_geometry.h +++ b/scene/3d/immediate_geometry.h @@ -38,6 +38,8 @@ class ImmediateGeometry : public GeometryInstance { RID im; + //a list of texures drawn need to be kept, to avoid references + // in VisualServer from becoming invalid if the texture is no longer used List<Ref<Texture> > cached_textures; bool empty; AABB aabb; @@ -47,7 +49,7 @@ protected: public: - void begin(Mesh::PrimitiveType p_primitive,const Ref<Texture>& p_texture); + void begin(Mesh::PrimitiveType p_primitive,const Ref<Texture>& p_texture=Ref<Texture>()); void set_normal(const Vector3& p_normal); void set_tangent(const Plane& p_tangent); void set_color(const Color& p_color); diff --git a/scene/3d/physics_joint.cpp b/scene/3d/physics_joint.cpp index 3f03b2aab3..084d96975f 100644 --- a/scene/3d/physics_joint.cpp +++ b/scene/3d/physics_joint.cpp @@ -369,9 +369,6 @@ RID HingeJoint::_configure_joint(PhysicsBody *body_a,PhysicsBody *body_b) { Transform gt = get_global_transform(); - Vector3 hingepos = gt.origin; - Vector3 hingedir = gt.basis.get_axis(2); - Transform ainv = body_a->get_global_transform().affine_inverse(); Transform local_a = ainv * gt; @@ -532,9 +529,6 @@ RID SliderJoint::_configure_joint(PhysicsBody *body_a,PhysicsBody *body_b) { Transform gt = get_global_transform(); - Vector3 sliderpos = gt.origin; - Vector3 sliderdir = gt.basis.get_axis(2); - Transform ainv = body_a->get_global_transform().affine_inverse(); Transform local_a = ainv * gt; diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp index d0b739e17f..c996a8123c 100644 --- a/scene/3d/skeleton.cpp +++ b/scene/3d/skeleton.cpp @@ -64,15 +64,17 @@ bool Skeleton::_set(const StringName& p_path, const Variant& p_value) { else if (what=="bound_childs") { Array children=p_value; - bones[which].nodes_bound.clear(); + if (is_inside_tree()) { + bones[which].nodes_bound.clear(); - for (int i=0;i<children.size();i++) { + for (int i=0;i<children.size();i++) { - NodePath path=children[i]; - ERR_CONTINUE( path.operator String()=="" ); - Node *node = get_node(path); - ERR_CONTINUE(!node); - bind_child_node_to_bone(which,node); + NodePath path=children[i]; + ERR_CONTINUE( path.operator String()=="" ); + Node *node = get_node(path); + ERR_CONTINUE(!node); + bind_child_node_to_bone(which,node); + } } } else { return false; diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index 8c86c4bf35..74cab30b17 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -585,6 +585,17 @@ Rect2 Sprite3D::get_item_rect() const { return Rect2(ofs,s); } + +void Sprite3D::_validate_property(PropertyInfo& property) const { + + if (property.name=="frame") { + + property.hint=PROPERTY_HINT_SPRITE_FRAME; + + property.hint_string="0,"+itos(vframes*hframes-1)+",1"; + } +} + void Sprite3D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_texture","texture:Texture"),&Sprite3D::set_texture); diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h index 41e6ba804a..31f8ec020f 100644 --- a/scene/3d/sprite_3d.h +++ b/scene/3d/sprite_3d.h @@ -158,6 +158,8 @@ class Sprite3D : public SpriteBase3D { protected: virtual void _draw(); static void _bind_methods(); + + virtual void _validate_property(PropertyInfo& property) const; public: diff --git a/scene/3d/vehicle_body.cpp b/scene/3d/vehicle_body.cpp index 6ccf07db1e..7c7957640f 100644 --- a/scene/3d/vehicle_body.cpp +++ b/scene/3d/vehicle_body.cpp @@ -488,7 +488,6 @@ real_t VehicleBody::_ray_cast(int p_idx,PhysicsDirectBodyState *s) { void VehicleBody::_update_suspension(PhysicsDirectBodyState *s) { - real_t deltaTime = s->get_step(); real_t chassisMass = mass; for (int w_it=0; w_it<wheels.size(); w_it++) @@ -596,21 +595,16 @@ void VehicleBody::_resolve_single_bilateral(PhysicsDirectBodyState *s, const Vec b2invinertia, b2invmass); - real_t jacDiagAB = jac.getDiagonal(); - real_t jacDiagABInv = real_t(1.) / jacDiagAB; - real_t rel_vel = jac.getRelativeVelocity( s->get_linear_velocity(), s->get_transform().basis.transposed().xform(s->get_angular_velocity()), b2lv, b2trans.xform(b2av)); - real_t a; - a=jacDiagABInv; rel_vel = normal.dot(vel); - //todo: move this into proper structure + //TODO: move this into proper structure real_t contactDamping = real_t(0.4); #define ONLY_USE_LINEAR_MASS #ifdef ONLY_USE_LINEAR_MASS @@ -642,16 +636,16 @@ VehicleBody::btVehicleWheelContactPoint::btVehicleWheelContactPoint(PhysicsDirec denom0= s->get_inverse_mass() + frictionDirectionWorld.dot(vec); } + /* TODO: Why is this code unused? if (body1) { Vector3 r0 = frictionPosWorld - body1->get_global_transform().origin; Vector3 c0 = (r0).cross(frictionDirectionWorld); Vector3 vec = s->get_inverse_inertia_tensor().xform_inv(c0).cross(r0); //denom1= body1->get_inverse_mass() + frictionDirectionWorld.dot(vec); - denom1=0; } - + */ real_t relaxation = 1.f; m_jacDiagABInv = relaxation/(denom0+denom1); diff --git a/scene/3d/visibility_notifier.cpp b/scene/3d/visibility_notifier.cpp index 60097ad482..f3b5cde0eb 100644 --- a/scene/3d/visibility_notifier.cpp +++ b/scene/3d/visibility_notifier.cpp @@ -221,9 +221,6 @@ void VisibilityEnabler::_notification(int p_what){ return; - Node *from = this; - //find where current scene starts - for (Map<Node*,Variant>::Element *E=nodes.front();E;E=E->next()) { if (!visible) @@ -242,17 +239,9 @@ void VisibilityEnabler::_change_node_state(Node* p_node,bool p_enabled) { { RigidBody *rb = p_node->cast_to<RigidBody>(); - if (rb) { - - if (p_enabled) { - RigidBody::Mode mode = RigidBody::Mode(nodes[p_node].operator int()); - //rb->set_mode(mode); - rb->set_sleeping(false); - } else { - //rb->set_mode(RigidBody::MODE_STATIC); - rb->set_sleeping(true); - } - } + if (rb) + + rb->set_sleeping(!p_enabled); } { diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp index 628edf09de..9488ae37a8 100644 --- a/scene/animation/animation_tree_player.cpp +++ b/scene/animation/animation_tree_player.cpp @@ -445,8 +445,44 @@ void AnimationTreePlayer::_notification(int p_what) { } +void AnimationTreePlayer::_compute_weights(float *p_fallback_weight, HashMap<NodePath,float> *p_weights, float p_coeff, const HashMap<NodePath,bool> *p_filter, float p_filtered_coeff) { -float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode **r_prev_anim,float p_weight, float p_time, bool p_seek,const HashMap<NodePath,bool> *p_filter, float p_reverse_weight) { + if (p_filter != NULL) { + + List<NodePath> key_list; + p_filter->get_key_list(&key_list); + + for (List<NodePath>::Element *E = key_list.front();E; E=E->next()) { + + if ((*p_filter)[E->get()]) { + + if (p_weights->has(E->get())) { + (*p_weights)[E->get()] *= p_filtered_coeff; + } else { + p_weights->set(E->get(), *p_fallback_weight * p_filtered_coeff); + } + + } else if (p_weights->has(E->get())) { + (*p_weights)[E->get()] *= p_coeff; + } + } + } + + List<NodePath> key_list; + p_weights->get_key_list(&key_list); + + for (List<NodePath>::Element *E = key_list.front();E;E=E->next()) { + if (p_filter == NULL || !p_filter->has(E->get())) { + (*p_weights)[E->get()] *= p_coeff; + } + } + + *p_fallback_weight *= p_coeff; + +} + + +float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode **r_prev_anim, float p_time, bool p_seek, float p_fallback_weight, HashMap<NodePath,float>* p_weights) { ERR_FAIL_COND_V(!node_map.has(p_node), 0); NodeBase *nb=node_map[p_node]; @@ -458,7 +494,16 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode case NODE_OUTPUT: { NodeOut *on = static_cast<NodeOut*>(nb); - return _process_node(on->inputs[0].node,r_prev_anim,p_weight,p_time,p_seek); + + for(TrackMap::Element *E=track_map.front();E;E=E->next()) { + E->get().total_weight = 0; + } + + HashMap<NodePath, float> weights; + + + + return _process_node(on->inputs[0].node,r_prev_anim,p_time,p_seek, p_fallback_weight, &weights); } break; case NODE_ANIMATION: { @@ -494,15 +539,21 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode } an->skip=true; + for (List<AnimationNode::TrackRef>::Element *E=an->tref.front();E;E=E->next()) { NodePath track_path = an->animation->track_get_path(E->get().local_track); - if (p_filter && p_filter->has(track_path)) { - E->get().weight = MAX(0, p_reverse_weight); - } else if(an->filter.has(track_path)) { + if (an->filter.has(track_path) && an->filter[track_path]) { E->get().weight = 0; - E->get().track->skip = true; + E->get().track->total_weight += p_fallback_weight; } else { - E->get().weight=p_weight; + if (p_weights->has(track_path)) { + float weight = (*p_weights)[track_path]; + E->get().weight = weight; + E->get().track->total_weight += weight; + } else { + E->get().weight = p_fallback_weight; + E->get().track->total_weight += p_fallback_weight; + } } if (E->get().weight>CMP_EPSILON) an->skip=false; @@ -531,7 +582,7 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode if (!osn->active) { //make it as if this node doesn't exist, pass input 0 by. - return _process_node(osn->inputs[0].node,r_prev_anim,p_weight,p_time,p_seek,p_filter,p_reverse_weight); + return _process_node(osn->inputs[0].node,r_prev_anim,p_time,p_seek, p_fallback_weight, p_weights); } float os_seek = p_seek; @@ -563,16 +614,14 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode float main_rem; float os_rem; - float os_reverse_weight = p_reverse_weight; - if (!osn->filter.empty()) { - p_filter = &osn->filter; - p_reverse_weight = p_weight; - os_reverse_weight = -1; - } + HashMap<NodePath, float> os_weights(*p_weights); + float os_fallback_weight = p_fallback_weight; + _compute_weights(&p_fallback_weight, p_weights, osn->mix?1.0 : 1.0 - blend, &osn->filter, 1.0); + _compute_weights(&os_fallback_weight, &os_weights, blend, &osn->filter, 0.0); - main_rem = _process_node(osn->inputs[0].node,r_prev_anim,(osn->mix?p_weight:p_weight*(1.0-blend)),p_time,p_seek,p_filter,p_reverse_weight); - os_rem = _process_node(osn->inputs[1].node,r_prev_anim,p_weight*blend,p_time,os_seek,p_filter,os_reverse_weight); + main_rem = _process_node(osn->inputs[0].node,r_prev_anim,p_time,p_seek, p_fallback_weight, p_weights); + os_rem = _process_node(osn->inputs[1].node,r_prev_anim,p_time,os_seek, os_fallback_weight, &os_weights); if (osn->start) { osn->remaining=os_rem; @@ -591,9 +640,11 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode case NODE_MIX: { MixNode *mn = static_cast<MixNode*>(nb); - - float rem = _process_node(mn->inputs[0].node,r_prev_anim,p_weight,p_time,p_seek,p_filter,p_reverse_weight); - _process_node(mn->inputs[1].node,r_prev_anim,p_weight*mn->amount,p_time,p_seek,p_filter,p_reverse_weight); + HashMap<NodePath, float> mn_weights(*p_weights); + float mn_fallback_weight = p_fallback_weight; + _compute_weights(&mn_fallback_weight, &mn_weights, mn->amount); + float rem = _process_node(mn->inputs[0].node,r_prev_anim, p_time,p_seek,p_fallback_weight,p_weights); + _process_node(mn->inputs[1].node,r_prev_anim,p_time,p_seek,mn_fallback_weight,&mn_weights); return rem; } break; @@ -601,16 +652,12 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode Blend2Node *bn = static_cast<Blend2Node*>(nb); - float rem; - if (!bn->filter.empty()) { - - rem = _process_node(bn->inputs[0].node,r_prev_anim,p_weight*(1.0-bn->value),p_time,p_seek,&bn->filter,p_weight); - _process_node(bn->inputs[1].node,r_prev_anim,p_weight*bn->value,p_time,p_seek,&bn->filter,-1); - - } else { - rem = _process_node(bn->inputs[0].node,r_prev_anim,p_weight*(1.0-bn->value),p_time,p_seek,p_filter,p_reverse_weight*(1.0-bn->value)); - _process_node(bn->inputs[1].node,r_prev_anim,p_weight*bn->value,p_time,p_seek,p_filter,p_reverse_weight*bn->value); - } + HashMap<NodePath, float> bn_weights(*p_weights); + float bn_fallback_weight = p_fallback_weight; + _compute_weights(&p_fallback_weight,p_weights, 1.0 - bn->value, &bn->filter, 1.0); + _compute_weights(&bn_fallback_weight,&bn_weights, bn->value, &bn->filter, 0.0); + float rem = _process_node(bn->inputs[0].node,r_prev_anim,p_time,p_seek,p_fallback_weight,p_weights); + _process_node(bn->inputs[1].node,r_prev_anim,p_time,p_seek,bn_fallback_weight,&bn_weights); return rem; } break; @@ -629,19 +676,39 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode upper_blend = bn->value; } - rem = _process_node(bn->inputs[1].node,r_prev_anim,p_weight*blend,p_time,p_seek,p_filter,p_reverse_weight*blend); - _process_node(bn->inputs[2].node,r_prev_anim,p_weight*upper_blend,p_time,p_seek,p_filter,p_reverse_weight*upper_blend); - _process_node(bn->inputs[0].node,r_prev_anim,p_weight*lower_blend,p_time,p_seek,p_filter,p_reverse_weight*lower_blend); + HashMap<NodePath, float> upper_weights(*p_weights); + float upper_fallback_weight = p_fallback_weight; + HashMap<NodePath, float> lower_weights(*p_weights); + float lower_fallback_weight = p_fallback_weight; + _compute_weights(&upper_fallback_weight,&upper_weights, upper_blend); + _compute_weights(&p_fallback_weight,p_weights, blend); + _compute_weights(&lower_fallback_weight,&lower_weights, lower_blend); + + rem = _process_node(bn->inputs[1].node,r_prev_anim,p_time,p_seek,p_fallback_weight,p_weights); + _process_node(bn->inputs[0].node,r_prev_anim,p_time,p_seek,lower_fallback_weight,&lower_weights); + _process_node(bn->inputs[2].node,r_prev_anim,p_time,p_seek,upper_fallback_weight,&upper_weights); return rem; } break; case NODE_BLEND4: { Blend4Node *bn = static_cast<Blend4Node*>(nb); - float rem = _process_node(bn->inputs[0].node,r_prev_anim,p_weight*(1.0-bn->value.x),p_time,p_seek,p_filter,p_reverse_weight*(1.0-bn->value.x)); - _process_node(bn->inputs[1].node,r_prev_anim,p_weight*bn->value.x,p_time,p_seek,p_filter,p_reverse_weight*bn->value.x); - float rem2 = _process_node(bn->inputs[2].node,r_prev_anim,p_weight*(1.0-bn->value.y),p_time,p_seek,p_filter,p_reverse_weight*(1.0-bn->value.y)); - _process_node(bn->inputs[3].node,r_prev_anim,p_weight*bn->value.y,p_time,p_seek,p_filter,p_reverse_weight*bn->value.y); + HashMap<NodePath, float> weights1(*p_weights); + float fallback_weight1 = p_fallback_weight; + HashMap<NodePath, float> weights2(*p_weights); + float fallback_weight2 = p_fallback_weight; + HashMap<NodePath, float> weights3(*p_weights); + float fallback_weight3 = p_fallback_weight; + + _compute_weights(&p_fallback_weight,p_weights, 1.0-bn->value.x); + _compute_weights(&fallback_weight1,&weights1, bn->value.x); + _compute_weights(&fallback_weight2,&weights2, 1.0-bn->value.y); + _compute_weights(&fallback_weight3,&weights3, bn->value.y); + + float rem = _process_node(bn->inputs[0].node,r_prev_anim,p_time,p_seek,p_fallback_weight,p_weights); + _process_node(bn->inputs[1].node,r_prev_anim,p_time,p_seek,fallback_weight1,&weights1); + float rem2 = _process_node(bn->inputs[2].node,r_prev_anim,p_time,p_seek,fallback_weight2,&weights2); + _process_node(bn->inputs[3].node,r_prev_anim,p_time,p_seek,fallback_weight3,&weights3); return MAX(rem,rem2); @@ -650,9 +717,9 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode TimeScaleNode *tsn = static_cast<TimeScaleNode*>(nb); float rem; if (p_seek) - rem = _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time,true,p_filter,p_reverse_weight); + rem = _process_node(tsn->inputs[0].node,r_prev_anim,p_time,true,p_fallback_weight,p_weights); else - rem = _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time*tsn->scale,false,p_filter,p_reverse_weight); + rem = _process_node(tsn->inputs[0].node,r_prev_anim,p_time*tsn->scale,false,p_fallback_weight,p_weights); if (tsn->scale == 0) return INFINITY; else @@ -669,16 +736,18 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode } tsn->seek_pos=-1; - return _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time,p_seek, p_filter, p_reverse_weight); + return _process_node(tsn->inputs[0].node,r_prev_anim,p_time,p_seek,p_fallback_weight,p_weights); } break; case NODE_TRANSITION: { TransitionNode *tn = static_cast<TransitionNode*>(nb); + HashMap<NodePath, float> prev_weights(*p_weights); + float prev_fallback_weight = p_fallback_weight; if (tn->prev<0) { // process current animation, check for transition - float rem = _process_node(tn->inputs[tn->current].node,r_prev_anim,p_weight,p_time,p_seek,p_filter,p_reverse_weight); + float rem = _process_node(tn->inputs[tn->current].node,r_prev_anim,p_time,p_seek,p_fallback_weight,p_weights); if (p_seek) tn->time=p_time; else @@ -698,22 +767,25 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode float rem; + _compute_weights(&p_fallback_weight,p_weights, 1.0-blend); + _compute_weights(&prev_fallback_weight,&prev_weights, blend); + if (!p_seek && tn->switched) { //just switched, seek to start of current - rem = _process_node(tn->inputs[tn->current].node,r_prev_anim,p_weight*(1.0-blend),0,true,p_filter,p_reverse_weight*(1.0-blend)); + rem = _process_node(tn->inputs[tn->current].node,r_prev_anim,0,true,p_fallback_weight,p_weights); } else { - rem = _process_node(tn->inputs[tn->current].node,r_prev_anim,p_weight*(1.0-blend),p_time,p_seek,p_filter,p_reverse_weight*(1.0-blend)); + rem = _process_node(tn->inputs[tn->current].node,r_prev_anim,p_time,p_seek,p_fallback_weight,p_weights); } tn->switched=false; if (p_seek) { // don't seek prev animation - _process_node(tn->inputs[tn->prev].node,r_prev_anim,p_weight*blend,0,false,p_filter,p_reverse_weight*blend); + _process_node(tn->inputs[tn->prev].node,r_prev_anim,0,false,prev_fallback_weight,&prev_weights); tn->time=p_time; } else { - _process_node(tn->inputs[tn->prev].node,r_prev_anim,p_weight*blend,p_time,false,p_filter,p_reverse_weight*blend); + _process_node(tn->inputs[tn->prev].node,r_prev_anim,p_time,false,prev_fallback_weight,&prev_weights); tn->time+=p_time; tn->prev_xfading-=p_time; if (tn->prev_xfading<0) { @@ -750,10 +822,11 @@ void AnimationTreePlayer::_process_animation(float p_delta) { AnimationNode *prev=NULL; if (reset_request) { - _process_node(out_name,&prev, 1.0, 0, true); + + _process_node(out_name,&prev, 0, true); reset_request=false; } else - _process_node(out_name,&prev, 1.0, p_delta); + _process_node(out_name,&prev, p_delta); if (dirty_caches) { //some animation changed.. ignore this pass @@ -802,7 +875,7 @@ void AnimationTreePlayer::_process_animation(float p_delta) { if (tr.track==NULL || tr.local_track<0 || tr.weight < CMP_EPSILON) continue; - float blend=tr.weight; + float blend=tr.weight / tr.track->total_weight; switch(a->track_get_type(tr.local_track)) { case Animation::TYPE_TRANSFORM: { ///< Transform a node or a bone. @@ -1904,6 +1977,3 @@ AnimationTreePlayer::~AnimationTreePlayer() { node_map.erase( node_map.front() ); } } - - - diff --git a/scene/animation/animation_tree_player.h b/scene/animation/animation_tree_player.h index dae891b5ce..6b5350e9ee 100644 --- a/scene/animation/animation_tree_player.h +++ b/scene/animation/animation_tree_player.h @@ -111,6 +111,7 @@ private: Variant value; bool skip; + float total_weight; }; @@ -273,7 +274,7 @@ private: Map<StringName,NodeBase*> node_map; // return time left to finish animation - float _process_node(const StringName& p_node,AnimationNode **r_prev_anim, float p_weight,float p_step, bool p_seek=false,const HashMap<NodePath,bool> *p_filter=NULL, float p_reverse_weight=0); + float _process_node(const StringName& p_node,AnimationNode **r_prev_anim,float p_step, bool p_seek=false, float p_fallback_weight = 1.0, HashMap<NodePath,float>* p_weights = NULL); void _process_animation(float p_delta); bool reset_request; @@ -283,6 +284,8 @@ private: void _recompute_caches(); void _recompute_caches(const StringName& p_node); DVector<String> _get_node_list(); + + void _compute_weights(float *p_fallback_weight, HashMap<NodePath,float> *p_weights, float p_coeff, const HashMap<NodePath,bool> *p_filter = NULL, float p_filtered_coeff = 0); protected: diff --git a/scene/audio/stream_player.cpp b/scene/audio/stream_player.cpp index 050e945c8f..99ecace1ed 100644 --- a/scene/audio/stream_player.cpp +++ b/scene/audio/stream_player.cpp @@ -77,7 +77,7 @@ void StreamPlayer::sp_update() { if (to_mix==0) { if (!stop_request) { stop_request=true; - call_deferred("stop"); + call_deferred("_do_stop"); } return; } @@ -91,7 +91,10 @@ void StreamPlayer::sp_update() { } } - +void StreamPlayer::_do_stop() { + stop(); + emit_signal("finished"); +} void StreamPlayer::_notification(int p_what) { @@ -181,7 +184,7 @@ void StreamPlayer::stop() { stop_request=false; playback->stop(); resampler.flush(); - emit_signal("finished"); + //set_idle_process(false); } @@ -381,6 +384,7 @@ void StreamPlayer::_bind_methods() { ObjectTypeDB::bind_method(_MD("_set_play","play"),&StreamPlayer::_set_play); ObjectTypeDB::bind_method(_MD("_get_play"),&StreamPlayer::_get_play); + ObjectTypeDB::bind_method(_MD("_do_stop"),&StreamPlayer::_do_stop); ADD_PROPERTY( PropertyInfo(Variant::OBJECT, "stream/stream", PROPERTY_HINT_RESOURCE_TYPE,"AudioStream"), _SCS("set_stream"), _SCS("get_stream") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/play"), _SCS("_set_play"), _SCS("_get_play") ); diff --git a/scene/audio/stream_player.h b/scene/audio/stream_player.h index 475139c2a4..4facc3c816 100644 --- a/scene/audio/stream_player.h +++ b/scene/audio/stream_player.h @@ -71,6 +71,8 @@ class StreamPlayer : public Node { AudioRBResampler resampler; + void _do_stop(); + bool _play; void _set_play(bool p_play); bool _get_play() const; diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index d7632b14b8..41d766c1b7 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -31,6 +31,7 @@ #include "print_string.h" #include "button_group.h" #include "scene/scene_string_names.h" +#include "scene/main/viewport.h" void BaseButton::_input_event(InputEvent p_event) { @@ -415,7 +416,11 @@ Ref<ShortCut> BaseButton:: get_shortcut() const { void BaseButton::_unhandled_input(InputEvent p_event) { - if (!is_disabled() && is_visible() && shortcut.is_valid() && shortcut->is_shortcut(p_event)) { + if (!is_disabled() && is_visible() && p_event.is_pressed() && !p_event.is_echo() && shortcut.is_valid() && shortcut->is_shortcut(p_event)) { + + if (get_viewport()->get_modal_stack_top() && !get_viewport()->get_modal_stack_top()->is_a_parent_of(this)) + return; //ignore because of modal window + if (is_toggle_mode()) { set_pressed(!is_pressed()); emit_signal("toggled",is_pressed()); diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index d6bbdf2d21..b69646432e 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -72,13 +72,16 @@ void ColorPicker::_notification(int p_what) { _update_color(); } - case NOTIFICATION_VISIBILITY_CHANGED: { - c_text->call_deferred("grab_focus"); - c_text->call_deferred("select"); - } break; + } } +void ColorPicker::set_focus_on_line_edit() { + + c_text->grab_focus(); + c_text->select(); +} + void ColorPicker::_update_controls() { if (edit_alpha) { @@ -137,14 +140,13 @@ void ColorPicker::_value_changed(double) { if (updating) return; - for(int i=0;i<3;i++) { + for(int i=0;i<4;i++) { color.components[i] = scroll[i]->get_val()/(raw_mode_enabled?1.0:255.0); } - color.components[3] = scroll[3]->get_val()/255.0; set_color(color); - c_text->set_text(color.to_html(edit_alpha && color.a<1)); + _update_text_value(); emit_signal("color_changed",color); @@ -171,22 +173,16 @@ void ColorPicker::_update_color() { for(int i=0;i<4;i++) { scroll[i]->set_max(255); scroll[i]->set_step(0.01); - if (raw_mode_enabled && i != 3) + if (raw_mode_enabled) { + if (i == 3) + scroll[i]->set_max(1); scroll[i]->set_val(color.components[i]); - else - scroll[i]->set_val(color.components[i]*255); + } else { + scroll[i]->set_val(color.components[i] * 255); + } } - if (text_is_constructor) { - String t = "Color("+String::num(color.r)+","+String::num(color.g)+","+String::num(color.b); - if (edit_alpha && color.a<1) - t+=(","+String::num(color.a)+")") ; - else - t+=")"; - c_text->set_text(t); - } else { - c_text->set_text(color.to_html(edit_alpha && color.a<1)); - } + _update_text_value(); sample->update(); updating=false; @@ -259,6 +255,20 @@ bool ColorPicker::is_raw_mode() const { return raw_mode_enabled; } + +void ColorPicker::_update_text_value() { + if (text_is_constructor) { + String t = "Color("+String::num(color.r)+","+String::num(color.g)+","+String::num(color.b); + if (edit_alpha && color.a<1) + t+=(","+String::num(color.a)+")") ; + else + t+=")"; + c_text->set_text(t); + } else { + c_text->set_text(color.to_html(edit_alpha && color.a<1)); + } +} + void ColorPicker::_sample_draw() { sample->draw_rect(Rect2(Point2(),Size2(256,20)),color); } @@ -268,12 +278,12 @@ void ColorPicker::_hsv_draw(int p_wich,Control* c) if (!c) return; if (p_wich==0) { - int x=c->get_size().x*s; - int y=c->get_size().y-c->get_size().y*v; + int x = CLAMP(c->get_size().x * s, 0, c->get_size().x); + int y = CLAMP(c->get_size().y-c->get_size().y * v, 0, c->get_size().y); Color col = color; col.a=1; 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(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) { int y=c->get_size().y-c->get_size().y*h; @@ -405,11 +415,12 @@ void ColorPicker::_screen_pick_pressed() if (!screen) { screen=memnew( Control ); r->add_child(screen); + screen->set_as_toplevel(true); screen->set_area_as_parent_rect(); screen->connect("input_event",this,"_screen_input"); } screen->raise(); - screen->show(); + screen->show_modal(); r->queue_screen_capture(); } @@ -628,6 +639,7 @@ void ColorPickerButton::pressed() { popup->set_pos(get_global_pos()-Size2(0,ms.height)); popup->set_size(ms); popup->popup(); + picker->set_focus_on_line_edit(); } diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index f5de982200..5e2cc57274 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -80,6 +80,7 @@ private: void _update_controls(); void _update_color(); void _update_presets(); + void _update_text_value(); void _text_type_toggled(); void _sample_draw(); void _hsv_draw(int p_wich,Control *c); @@ -107,6 +108,7 @@ public: void set_raw_mode(bool p_enabled); bool is_raw_mode() const; + void set_focus_on_line_edit(); ColorPicker(); }; diff --git a/scene/gui/color_ramp_edit.cpp b/scene/gui/color_ramp_edit.cpp index 50e1ffbec9..b7347f00dc 100644 --- a/scene/gui/color_ramp_edit.cpp +++ b/scene/gui/color_ramp_edit.cpp @@ -271,7 +271,9 @@ void ColorRampEdit::_input_event(const InputEvent& p_event) { void ColorRampEdit::_notification(int p_what) { if (p_what==NOTIFICATION_ENTER_TREE) { - picker->connect("color_changed",this,"_color_changed"); + if (!picker->is_connected("color_changed",this,"_color_changed")) { + picker->connect("color_changed",this,"_color_changed"); + } } if (p_what==NOTIFICATION_DRAW) { diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 2e28baa137..c08e10b9ff 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -49,14 +49,22 @@ Variant Control::edit_get_state() const { - return get_rect(); + Dictionary s; + s["rect"]=get_rect(); + s["rot"]=get_rotation(); + s["scale"]=get_scale(); + return s; } void Control::edit_set_state(const Variant& p_state) { - Rect2 state=p_state; + Dictionary s=p_state; + + Rect2 state=s["rect"]; set_pos(state.pos); set_size(state.size); + set_rotation(s["rot"]); + set_scale(s["scale"]); } void Control::set_custom_minimum_size(const Size2& p_custom) { @@ -754,6 +762,11 @@ bool Control::is_window_modal_on_top() const { return get_viewport()->_gui_is_modal_on_top(this); } +uint64_t Control::get_modal_frame() const { + + return data.modal_frame; +} + Size2 Control::get_minimum_size() const { @@ -1829,6 +1842,7 @@ void Control::show_modal(bool p_exclusive) { raise(); data.modal_exclusive=p_exclusive; data.MI=get_viewport()->_gui_show_modal(this); + data.modal_frame=OS::get_singleton()->get_frames_drawn(); } @@ -1851,7 +1865,7 @@ void Control::_modal_stack_remove() { } -void Control::_propagate_theme_changed(CanvasItem *p_at,Control *p_owner) { +void Control::_propagate_theme_changed(CanvasItem *p_at,Control *p_owner,bool p_assign) { Control *c = p_at->cast_to<Control>(); @@ -1870,15 +1884,30 @@ void Control::_propagate_theme_changed(CanvasItem *p_at,Control *p_owner) { if (c) { - c->data.theme_owner=p_owner; + if (p_assign) { + c->data.theme_owner=p_owner; + } c->_notification(NOTIFICATION_THEME_CHANGED); c->update(); } } + +void Control::_theme_changed() { + + _propagate_theme_changed(this,this,false); +} + void Control::set_theme(const Ref<Theme>& p_theme) { + if (data.theme==p_theme) + return; + + if (data.theme.is_valid()) { + data.theme->disconnect("changed",this,"_theme_changed"); + } + data.theme=p_theme; if (!p_theme.is_null()) { @@ -1895,6 +1924,9 @@ void Control::set_theme(const Ref<Theme>& p_theme) { } + if (data.theme.is_valid()) { + data.theme->connect("changed",this,"_theme_changed"); + } } @@ -2230,6 +2262,7 @@ void Control::set_rotation(float p_radians) { data.rotation=p_radians; update(); _notify_transform(); + _change_notify("rect/rotation"); } float Control::get_rotation() const{ @@ -2434,6 +2467,10 @@ void Control::_bind_methods() { ObjectTypeDB::bind_method(_MD("minimum_size_changed"), &Control::minimum_size_changed); + ObjectTypeDB::bind_method(_MD("_theme_changed"), &Control::_theme_changed); + + + ObjectTypeDB::bind_method(_MD("_font_changed"), &Control::_font_changed); BIND_VMETHOD(MethodInfo("_input_event",PropertyInfo(Variant::INPUT_EVENT,"event"))); @@ -2539,6 +2576,7 @@ Control::Control() { data.parent_canvas_item=NULL; data.scale=Vector2(1,1); data.drag_owner=0; + data.modal_frame=0; for (int i=0;i<4;i++) { diff --git a/scene/gui/control.h b/scene/gui/control.h index 07a28de1ea..1337cbc4b9 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -132,6 +132,7 @@ private: ObjectID drag_owner; bool modal; bool modal_exclusive; + uint64_t modal_frame; //frame used to put something as modal Ref<Theme> theme; Control *theme_owner; String tooltip; @@ -171,7 +172,9 @@ private: float _get_range(int p_idx) const; float _s2a(float p_val, AnchorType p_anchor,float p_range) const; float _a2s(float p_val, AnchorType p_anchor,float p_range) const; - void _propagate_theme_changed(CanvasItem *p_at, Control *p_owner); + void _propagate_theme_changed(CanvasItem *p_at, Control *p_owner, bool p_assign=true); + void _theme_changed(); + void _change_notify_margins(); void _update_minimum_size(); @@ -249,6 +252,7 @@ public: Size2 get_custom_minimum_size() const; bool is_window_modal_on_top() const; + uint64_t get_modal_frame() const; //frame in which this was made modal Control *get_parent_control() const; diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index 6342391383..4dbc106834 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -62,7 +62,6 @@ void WindowDialog::_input_event(const InputEvent& p_event) { Point2 rel( p_event.mouse_motion.relative_x, p_event.mouse_motion.relative_y ); Point2 pos = get_pos(); - Size2 size = get_size(); pos+=rel; @@ -409,7 +408,6 @@ AcceptDialog::AcceptDialog() { ok->set_text(RTR("OK")); hbc->add_child(ok); hbc->add_spacer(); - //add_child(ok); ok->connect("pressed", this,"_ok"); diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index ee3b8913b4..06b1c42690 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -774,7 +774,6 @@ void GraphEdit::set_zoom(float p_zoom) { Vector2 sbofs = (Vector2( h_scroll->get_val(), v_scroll->get_val() ) + get_size()/2)/zoom; - float prev_zoom = zoom; zoom = p_zoom; top_layer->update(); diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index 94001b2ac1..3705541865 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -559,7 +559,12 @@ Color GraphNode::get_connection_output_color(int p_idx) { void GraphNode::_input_event(const InputEvent& p_ev) { if (p_ev.type==InputEvent::MOUSE_BUTTON) { + + ERR_EXPLAIN("GraphNode must be the child of a GraphEdit node."); + ERR_FAIL_COND(get_parent_control() == NULL); + get_parent_control()->grab_focus(); + if(p_ev.mouse_button.pressed && p_ev.mouse_button.button_index==BUTTON_LEFT) { Vector2 mpos = Vector2(p_ev.mouse_button.x,p_ev.mouse_button.y); diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp index dde9768a6d..5e6622b3f8 100644 --- a/scene/gui/grid_container.cpp +++ b/scene/gui/grid_container.cpp @@ -156,6 +156,7 @@ void GridContainer::_notification(int p_what) { void GridContainer::set_columns(int p_columns) { + ERR_FAIL_COND(p_columns<1); columns=p_columns; queue_sort(); minimum_size_changed(); diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 5379836746..105d919338 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -191,7 +191,7 @@ void ItemList::set_item_disabled(int p_idx,bool p_disabled){ ERR_FAIL_INDEX(p_idx,items.size()); items[p_idx].disabled=p_disabled; - + update(); } @@ -225,7 +225,7 @@ void ItemList::select(int p_idx,bool p_single){ if (p_single || select_mode==SELECT_SINGLE) { - if (!items[p_idx].selectable) { + if (!items[p_idx].selectable || items[p_idx].disabled) { return; } @@ -237,7 +237,7 @@ void ItemList::select(int p_idx,bool p_single){ ensure_selected_visible=false; } else { - if (items[p_idx].selectable) { + if (items[p_idx].selectable && !items[p_idx].disabled) { items[p_idx].selected=true; } } @@ -336,6 +336,7 @@ void ItemList::clear(){ current=-1; ensure_selected_visible=false; update(); + shape_changed=true; defer_select_single=-1; } @@ -461,7 +462,6 @@ void ItemList::_input_event(const InputEvent& p_event) { pos.y+=scroll_bar->get_val(); int closest = -1; - int closest_dist=0x7FFFFFFF; for(int i=0;i<items.size();i++) { @@ -474,12 +474,6 @@ void ItemList::_input_event(const InputEvent& p_event) { closest=i; break; } - - float dist = rc.distance_to(pos); - if (dist<closest_dist) { - closest=i; - closest_dist=dist; - } } if (closest!=-1) { @@ -510,7 +504,7 @@ void ItemList::_input_event(const InputEvent& p_event) { } } else { - if (!mb.doubleclick && !mb.mod.command && select_mode==SELECT_MULTI && items[i].selectable && items[i].selected && p_event.mouse_button.button_index==BUTTON_LEFT) { + if (!mb.doubleclick && !mb.mod.command && select_mode==SELECT_MULTI && items[i].selectable && !items[i].disabled && items[i].selected && p_event.mouse_button.button_index==BUTTON_LEFT) { defer_select_single=i; return; } @@ -546,6 +540,11 @@ void ItemList::_input_event(const InputEvent& p_event) { return; + } else { + Vector<int> sItems = get_selected_items(); + for(int i = 0; i < sItems.size(); i++) { + unselect(sItems[i]); + } } } if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==BUTTON_WHEEL_UP && p_event.mouse_button.pressed) { @@ -694,7 +693,7 @@ void ItemList::_input_event(const InputEvent& p_event) { if (select_mode==SELECT_MULTI && current>=0 && current<items.size()) { - if (items[current].selectable && !items[current].selected) { + if (items[current].selectable && !items[current].disabled && !items[current].selected) { select(current,false); emit_signal("multi_selected",current,true); } else if (items[current].selected) { @@ -823,7 +822,7 @@ void ItemList::_notification(int p_what) { } if (shape_changed) { - + float max_column_width = 0; //1- compute item minimum sizes @@ -914,11 +913,11 @@ void ItemList::_notification(int p_what) { if (i<items.size()-1) separators.push_back(ofs.y+max_h+vseparation/2); - + for(int j=i;j>=0 && col>0;j--, col--) { items[j].rect_cache.size.y = max_h; } - + ofs.x=0; ofs.y+=max_h+vseparation; col=0; @@ -1029,10 +1028,14 @@ void ItemList::_notification(int p_what) { draw_rect.size=adj.size; } + Color modulate=Color(1,1,1,1); + if (items[i].disabled) + modulate.a*=0.5; + if (items[i].icon_region.has_no_area()) - draw_texture_rect(items[i].icon, draw_rect ); + draw_texture_rect(items[i].icon, draw_rect,false,modulate ); else - draw_texture_rect_region(items[i].icon, draw_rect, items[i].icon_region); + draw_texture_rect_region(items[i].icon, draw_rect, items[i].icon_region,modulate); } @@ -1053,6 +1056,10 @@ void ItemList::_notification(int p_what) { else max_len=size.x; + Color modulate=items[i].selected?font_color_selected:font_color; + if (items[i].disabled) + modulate.a*=0.5; + if (icon_mode==ICON_MODE_TOP && max_text_lines>0) { int ss = items[i].text.length(); @@ -1090,7 +1097,7 @@ void ItemList::_notification(int p_what) { if (line>=max_text_lines) break; } - ofs+=font->draw_char(get_canvas_item(),text_ofs+Vector2(ofs+(max_len-line_size_cache[line])/2,line*(font_height+line_separation)).floor(),items[i].text[j],items[i].text[j+1],items[i].selected?font_color_selected:font_color); + ofs+=font->draw_char(get_canvas_item(),text_ofs+Vector2(ofs+(max_len-line_size_cache[line])/2,line*(font_height+line_separation)).floor(),items[i].text[j],items[i].text[j+1],modulate); } //special multiline mode @@ -1110,7 +1117,7 @@ void ItemList::_notification(int p_what) { text_ofs+=base_ofs; text_ofs+=items[i].rect_cache.pos; - draw_string(font,text_ofs,items[i].text,items[i].selected?font_color_selected:font_color,max_len+1); + draw_string(font,text_ofs,items[i].text,modulate,max_len+1); } @@ -1203,8 +1210,11 @@ String ItemList::get_tooltip(const Point2& p_pos) const { } void ItemList::sort_items_by_text() { + items.sort(); update(); + shape_changed=true; + if (select_mode==SELECT_SINGLE) { for(int i=0;i<items.size();i++) { if (items[i].selected) { @@ -1245,6 +1255,19 @@ real_t ItemList::get_icon_scale() const { return icon_scale; } +Vector<int> ItemList::get_selected_items() { + Vector<int> selected; + for (int i = 0; i < items.size(); i++) { + if (items[i].selected) { + selected.push_back(i); + if (this->select_mode == SELECT_SINGLE) { + break; + } + } + } + return selected; +} + void ItemList::_bind_methods(){ ObjectTypeDB::bind_method(_MD("add_item","text","icon:Texture","selectable"),&ItemList::add_item,DEFVAL(Variant()),DEFVAL(true)); @@ -1277,12 +1300,13 @@ void ItemList::_bind_methods(){ ObjectTypeDB::bind_method(_MD("select","idx","single"),&ItemList::select,DEFVAL(true)); ObjectTypeDB::bind_method(_MD("unselect","idx"),&ItemList::unselect); ObjectTypeDB::bind_method(_MD("is_selected","idx"),&ItemList::is_selected); + ObjectTypeDB::bind_method(_MD("get_selected_items"),&ItemList::get_selected_items); ObjectTypeDB::bind_method(_MD("get_item_count"),&ItemList::get_item_count); ObjectTypeDB::bind_method(_MD("remove_item","idx"),&ItemList::remove_item); ObjectTypeDB::bind_method(_MD("clear"),&ItemList::clear); - ObjectTypeDB::bind_method(_MD("sort_items_by_text"),&ItemList::clear); + ObjectTypeDB::bind_method(_MD("sort_items_by_text"),&ItemList::sort_items_by_text); ObjectTypeDB::bind_method(_MD("set_fixed_column_width","width"),&ItemList::set_fixed_column_width); ObjectTypeDB::bind_method(_MD("get_fixed_column_width"),&ItemList::get_fixed_column_width); @@ -1330,8 +1354,6 @@ void ItemList::_bind_methods(){ ADD_SIGNAL( MethodInfo("item_activated",PropertyInfo(Variant::INT,"index"))); } - - ItemList::ItemList() { current=-1; @@ -1363,4 +1385,3 @@ ItemList::ItemList() { ItemList::~ItemList() { } - diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h index aa6dd64c50..e1902d1c1f 100644 --- a/scene/gui/item_list.h +++ b/scene/gui/item_list.h @@ -144,6 +144,7 @@ public: void select(int p_idx,bool p_single=true); void unselect(int p_idx); bool is_selected(int p_idx) const; + Vector<int> get_selected_items(); void set_current(int p_current); int get_current() const; diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index 2d4438c48c..4c025e92df 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -144,7 +144,6 @@ void Label::_notification(int p_what) { if (!wc) return; - int c = 0; int line=0; int line_to=lines_skipped + (lines_visible>0?lines_visible:1); while(wc) { @@ -357,6 +356,21 @@ int Label::get_line_count() const { return line_count; } +int Label::get_visible_line_count() const { + + int line_spacing = get_constant("line_spacing"); + int font_h = get_font("font")->get_height()+line_spacing; + int lines_visible = (get_size().y+line_spacing)/font_h; + + if (lines_visible > line_count) + lines_visible = line_count; + + if (max_lines_visible >= 0 && lines_visible > max_lines_visible) + lines_visible = max_lines_visible; + + return lines_visible; +} + void Label::regenerate_word_cache() { while (word_cache) { @@ -536,7 +550,9 @@ void Label::set_text(const String& p_string) { if (percent_visible<1) visible_chars=get_total_character_count()*percent_visible; update(); - minimum_size_changed(); + if (!autowrap) { + minimum_size_changed(); + } } @@ -639,6 +655,7 @@ void Label::_bind_methods() { ObjectTypeDB::bind_method(_MD("is_uppercase"),&Label::is_uppercase); ObjectTypeDB::bind_method(_MD("get_line_height"),&Label::get_line_height); ObjectTypeDB::bind_method(_MD("get_line_count"),&Label::get_line_count); + ObjectTypeDB::bind_method(_MD("get_visible_line_count"),&Label::get_visible_line_count); ObjectTypeDB::bind_method(_MD("get_total_character_count"),&Label::get_total_character_count); ObjectTypeDB::bind_method(_MD("set_visible_characters","amount"),&Label::set_visible_characters); ObjectTypeDB::bind_method(_MD("get_visible_characters"),&Label::get_visible_characters); diff --git a/scene/gui/label.h b/scene/gui/label.h index 3c14add60d..b472eca1a2 100644 --- a/scene/gui/label.h +++ b/scene/gui/label.h @@ -132,6 +132,7 @@ public: int get_line_height() const; int get_line_count() const; + int get_visible_line_count() const; Label(const String& p_text=String()); ~Label(); diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 579a6e2f0a..89c235e101 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -31,6 +31,7 @@ #include "os/os.h" #include "print_string.h" #include "label.h" +#include "translation.h" #ifdef TOOLS_ENABLED #include "tools/editor/editor_settings.h" #endif @@ -108,7 +109,7 @@ void LineEdit::_input_event(InputEvent p_event) { selection.doubleclick=false; if (OS::get_singleton()->has_virtual_keyboard()) - OS::get_singleton()->show_virtual_keyboard(get_text(),get_global_rect()); + OS::get_singleton()->show_virtual_keyboard(text,get_global_rect()); } update(); @@ -117,7 +118,7 @@ void LineEdit::_input_event(InputEvent p_event) { const InputEventMouseMotion& m=p_event.mouse_motion; - if (m.button_mask&1) { + if (m.button_mask&BUTTON_LEFT) { if (selection.creating) { set_cursor_at_pixel_pos(m.x); @@ -556,7 +557,9 @@ void LineEdit::_notification(int p_what) { cursor_set_blink_enabled(EDITOR_DEF("text_editor/caret_blink", false)); cursor_set_blink_speed(EDITOR_DEF("text_editor/caret_blink_speed", 0.65)); - EditorSettings::get_singleton()->connect("settings_changed",this,"_editor_settings_changed"); + if (!EditorSettings::get_singleton()->is_connected("settings_changed",this,"_editor_settings_changed")) { + EditorSettings::get_singleton()->connect("settings_changed",this,"_editor_settings_changed"); + } } } break; #endif @@ -613,11 +616,11 @@ void LineEdit::_notification(int p_what) { } break; case ALIGN_CENTER: { - x_ofs=x_ofs=int(size.width-(cached_width))/2; + x_ofs=int(size.width-(cached_width))/2; } break; case ALIGN_RIGHT: { - x_ofs=x_ofs=int(size.width-style->get_offset().x-(cached_width)); + x_ofs=int(size.width-style->get_offset().x-(cached_width)); } break; } @@ -634,14 +637,19 @@ void LineEdit::_notification(int p_what) { Color font_color_selected=get_color("font_color_selected"); Color cursor_color=get_color("cursor_color"); + const String& t = text.empty() ? placeholder : text; + // draw placeholder color + if(text.empty()) + font_color.a *= placeholder_alpha; + while(true) { //end of string, break! - if (char_ofs>=text.length()) + if (char_ofs>=t.length()) break; - CharType cchar=pass?'*':text[char_ofs]; - CharType next=pass?'*':text[char_ofs+1]; + CharType cchar=pass?'*':t[char_ofs]; + CharType next=pass?'*':t[char_ofs+1]; int char_width=font->get_char_size( cchar,next ).width; // end of widget, break! @@ -678,7 +686,7 @@ void LineEdit::_notification(int p_what) { } if (OS::get_singleton()->has_virtual_keyboard()) - OS::get_singleton()->show_virtual_keyboard(get_text(),get_global_rect()); + OS::get_singleton()->show_virtual_keyboard(text,get_global_rect()); } break; case NOTIFICATION_FOCUS_EXIT: { @@ -803,6 +811,9 @@ void LineEdit::set_cursor_at_pixel_pos(int p_x) { if ( (pixel_ofs-p_x) < (char_w >> 1 ) ) { ofs+=1; + } else if ( (pixel_ofs-p_x) > (char_w >> 1 ) ) { + + ofs-=1; } break; @@ -938,6 +949,29 @@ String LineEdit::get_text() const { return text; } +void LineEdit::set_placeholder(String p_text) { + + placeholder = XL_MESSAGE(p_text); + update(); +} + +String LineEdit::get_placeholder() const { + + return placeholder; +} + + +void LineEdit::set_placeholder_alpha(float p_alpha) { + + placeholder_alpha = p_alpha; + update(); +} + +float LineEdit::get_placeholder_alpha() const { + + return placeholder_alpha; +} + void LineEdit::set_cursor_pos(int p_pos) { if (p_pos>(int)text.length()) @@ -950,10 +984,6 @@ void LineEdit::set_cursor_pos(int p_pos) { cursor_pos=p_pos; -// if (cursor_pos>(window_pos+get_window_length())) { -// set_window_pos(cursor_pos-get_window_lengt//h()); -// } - if (!is_inside_tree()) { window_pos=cursor_pos; @@ -972,7 +1002,6 @@ void LineEdit::set_cursor_pos(int p_pos) { if (window_width<0) return; - int width_to_cursor=0; int wp=window_pos; if (font.is_valid()) { @@ -1223,6 +1252,10 @@ void LineEdit::_bind_methods() { ObjectTypeDB::bind_method(_MD("select_all"),&LineEdit::select_all); ObjectTypeDB::bind_method(_MD("set_text","text"),&LineEdit::set_text); ObjectTypeDB::bind_method(_MD("get_text"),&LineEdit::get_text); + ObjectTypeDB::bind_method(_MD("set_placeholder","text"),&LineEdit::set_placeholder); + ObjectTypeDB::bind_method(_MD("get_placeholder"),&LineEdit::get_placeholder); + ObjectTypeDB::bind_method(_MD("set_placeholder_alpha","alpha"),&LineEdit::set_placeholder_alpha); + ObjectTypeDB::bind_method(_MD("get_placeholder_alpha"),&LineEdit::get_placeholder_alpha); ObjectTypeDB::bind_method(_MD("set_cursor_pos","pos"),&LineEdit::set_cursor_pos); ObjectTypeDB::bind_method(_MD("get_cursor_pos"),&LineEdit::get_cursor_pos); ObjectTypeDB::bind_method(_MD("cursor_set_blink_enabled", "enable"),&LineEdit::cursor_set_blink_enabled); @@ -1257,6 +1290,8 @@ void LineEdit::_bind_methods() { BIND_CONSTANT( MENU_MAX ); ADD_PROPERTYNZ( PropertyInfo( Variant::STRING, "text" ), _SCS("set_text"),_SCS("get_text") ); + ADD_PROPERTYNZ( PropertyInfo( Variant::STRING, "placeholder/text" ), _SCS("set_placeholder"),_SCS("get_placeholder") ); + ADD_PROPERTYNZ( PropertyInfo( Variant::REAL, "placeholder/alpha",PROPERTY_HINT_RANGE,"0,1,0.001" ), _SCS("set_placeholder_alpha"),_SCS("get_placeholder_alpha") ); ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), _SCS("set_align"), _SCS("get_align")); ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "max_length" ), _SCS("set_max_length"),_SCS("get_max_length") ); ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "editable" ), _SCS("set_editable"),_SCS("is_editable") ); @@ -1275,6 +1310,7 @@ LineEdit::LineEdit() { window_has_focus=true; max_length = 0; pass=false; + placeholder_alpha=0.6; selection_clear(); set_focus_mode( FOCUS_ALL ); diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index e4da0f0b87..112e4ad55e 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -67,6 +67,8 @@ private: String undo_text; String text; + String placeholder; + float placeholder_alpha; PopupMenu *menu; @@ -135,6 +137,10 @@ public: void delete_text(int p_from_column, int p_to_column); void set_text(String p_text); String get_text() const; + void set_placeholder(String p_text); + String get_placeholder() const; + void set_placeholder_alpha(float p_alpha); + float get_placeholder_alpha() const; void set_cursor_pos(int p_pos); int get_cursor_pos() const; void set_max_length(int p_max_length); diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index 28d67287d5..725f1ddf17 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -28,6 +28,7 @@ /*************************************************************************/ #include "menu_button.h" #include "os/keyboard.h" +#include "scene/main/viewport.h" void MenuButton::_unhandled_key_input(InputEvent p_event) { @@ -38,8 +39,12 @@ void MenuButton::_unhandled_key_input(InputEvent p_event) { if (!get_parent() || !is_visible() || is_disabled()) return; + if (get_viewport()->get_modal_stack_top() && !get_viewport()->get_modal_stack_top()->is_a_parent_of(this)) + return; //ignore because of modal window - int item = popup->activate_item_by_event(p_event); + + if (popup->activate_item_by_event(p_event)) + accept_event(); } } diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index 8d02d0e4e5..5b83c3f8b8 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -125,8 +125,6 @@ void Popup::set_as_minsize() { } - print_line(String(c->get_type())+": "+minsize); - total_minsize.width = MAX( total_minsize.width, minsize.width ); total_minsize.height = MAX( total_minsize.height, minsize.height ); } @@ -168,8 +166,6 @@ void Popup::popup_centered_minsize(const Size2& p_minsize) { } - print_line(String(c->get_type())+": "+minsize); - total_minsize.width = MAX( total_minsize.width, minsize.width ); total_minsize.height = MAX( total_minsize.height, minsize.height ); } diff --git a/scene/gui/progress_bar.cpp b/scene/gui/progress_bar.cpp index 02da8ff27e..8af94c3638 100644 --- a/scene/gui/progress_bar.cpp +++ b/scene/gui/progress_bar.cpp @@ -51,7 +51,6 @@ void ProgressBar::_notification(int p_what) { Ref<StyleBox> fg = get_stylebox("fg"); Ref<Font> font = get_font("font"); Color font_color=get_color("font_color"); - Color font_color_shadow=get_color("font_color_shadow"); draw_style_box(bg,Rect2(Point2(),get_size())); float r = get_unit_value(); @@ -63,7 +62,6 @@ void ProgressBar::_notification(int p_what) { } if (percent_visible) { - int fh=font->get_height(); String txt=itos(int(get_unit_value()*100))+"%"; font->draw_halign(get_canvas_item(),Point2(0,font->get_ascent()+(get_size().height-font->get_height())/2),HALIGN_CENTER,get_size().width,txt,font_color); } diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 786ce27a0c..73a3cda5f3 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -270,7 +270,6 @@ if (m_height > line_height) {\ if (p_mode!=PROCESS_CACHE) { lh=line<l.height_caches.size()?l.height_caches[line]:1; } - bool found_space=false; while (c[end]!=0 && !(end && c[end-1]==' ' && c[end]!=' ')) { @@ -284,30 +283,13 @@ if (m_height > line_height) {\ } w+=cw; - - if (c[end]==' ') { - - fw+=cw; - /* - if (p_mode==PROCESS_CACHE) { - fw+=cw; - } else if (align==ALIGN_FILL && line<l.space_caches.size() && l.space_caches[line]>0) { - //print_line(String(c,end)+": "+itos(l.offset_caches[line])+"/"+itos(l.space_caches[line])); - //sub_space=cw; - found_space=true; - } else { - fw+=cw; - }*/ - } else { - fw+=cw; - } + fw+=cw; end++; } ENSURE_WIDTH(w); - //print_line("END: "+String::chr(c[end])+"."); if (end && c[end-1]==' ') { if (p_mode==PROCESS_CACHE) { spaces_size+=font->get_char_size(' ').width; @@ -319,27 +301,17 @@ if (m_height > line_height) {\ } spaces++; - /* - if (found_space) { - int ln = MIN(l.offset_caches.size()-1,line); - - fw+=l.offset_caches[ln]/l.space_caches[ln]; - }*/ - } { - int ofs=0; for(int i=0;i<end;i++) { int pofs=wofs+ofs; - - if (p_mode==PROCESS_POINTER && r_click_char && p_click_pos.y>=p_ofs.y+y && p_click_pos.y<=p_ofs.y+y+lh) { //int o = (wofs+w)-p_click_pos.x; @@ -354,15 +326,6 @@ if (m_height > line_height) {\ if (p_click_pos.x-cw/2>p_ofs.x+align_ofs+pofs) { rchar=int((&c[i])-cf); - //print_line("GOT: "+itos(rchar)); - - - //if (i==end-1 && p_click_pos.x+cw/2 > pofs) - // rchar++; - //int o = (wofs+w)-p_click_pos.x; - - // if (o>cw/2) - // rchar++; } @@ -402,12 +365,9 @@ if (m_height > line_height) {\ } - //print_line("draw char: "+String::chr(c[i])); - if (underline) { Color uc=color; uc.a*=0.5; - //VS::get_singleton()->canvas_item_add_line(ci,Point2(pofs,y+ascent+2),Point2(pofs+cw,y+ascent+2),uc); int uy = y+lh-fh+ascent+2; VS::get_singleton()->canvas_item_add_line(ci,p_ofs+Point2(align_ofs+pofs,uy),p_ofs+Point2(align_ofs+pofs+cw,uy),uc); } @@ -462,28 +422,6 @@ if (m_height > line_height) {\ if (p_mode!=PROCESS_CACHE) lh = line<l.height_caches.size()?l.height_caches[line]:1; - -#if 0 - if (p_mode==PROCESS_POINTER && r_click_item ) { - //previous last "wrapped" line - int pl = line-1; - if (pl<0 || lines[pl].height_caches.size()==0) - break; - int py=lines[pl].offset_caches[ lines[pl].offset_caches.size() -1 ]; - int ph=lines[pl].height_caches[ lines[pl].height_caches.size() -1 ]; - print_line("py: "+itos(py)); - print_line("ph: "+itos(ph)); - - rchar=0; - if (p_click_pos.y>=py && p_click_pos.y<=py+ph) { - if (r_outside) *r_outside=true; - *r_click_item=it; - *r_click_char=rchar; - return; - } - } - -#endif } break; case ITEM_TABLE: { @@ -493,7 +431,6 @@ if (m_height > line_height) {\ int vseparation=get_constant("table_vseparation"); Color ccolor = _find_color(table,p_base_color); Vector2 draw_ofs = Point2(wofs,y); - int max_y=get_size().height; if (p_mode==PROCESS_CACHE) { @@ -725,8 +662,9 @@ void RichTextLabel::_notification(int p_what) { } break; case NOTIFICATION_ENTER_TREE: { - if (use_bbcode) - parse_bbcode(bbcode); + if (bbcode != "") + set_bbcode(bbcode); + main->first_invalid_line=0; //invalidate ALL update(); @@ -1503,7 +1441,6 @@ bool RichTextLabel::is_scroll_following() const { Error RichTextLabel::parse_bbcode(const String& p_bbcode) { - clear(); return append_bbcode(p_bbcode); } @@ -1825,7 +1762,6 @@ bool RichTextLabel::search(const String& p_string,bool p_from_selection) { charidx=selection.to_char+1; } - int line=-1; while(it) { if (it->type==ITEM_TEXT) { @@ -1922,6 +1858,10 @@ void RichTextLabel::set_bbcode(const String& p_bbcode) { bbcode=p_bbcode; if (is_inside_tree() && use_bbcode) parse_bbcode(p_bbcode); + else { // raw text + clear(); + add_text(p_bbcode); + } } String RichTextLabel::get_bbcode() const { @@ -1933,19 +1873,37 @@ void RichTextLabel::set_use_bbcode(bool p_enable) { if (use_bbcode==p_enable) return; use_bbcode=p_enable; - if (is_inside_tree() && use_bbcode) - parse_bbcode(bbcode); + set_bbcode(bbcode); } bool RichTextLabel::is_using_bbcode() const { return use_bbcode; } + +String RichTextLabel::get_text() { + String text = ""; + Item *it = main; + while (it) { + if (it->type == ITEM_TEXT) { + ItemText *t = static_cast<ItemText*>(it); + text += t->text; + } else if (it->type == ITEM_NEWLINE) { + text += "\n"; + } else if (it->type == ITEM_INDENT) { + text += "\t"; + } + it=_get_next_item(it,true); + } + return text; +} + void RichTextLabel::_bind_methods() { ObjectTypeDB::bind_method(_MD("_input_event"),&RichTextLabel::_input_event); ObjectTypeDB::bind_method(_MD("_scroll_changed"),&RichTextLabel::_scroll_changed); + ObjectTypeDB::bind_method(_MD("get_text"),&RichTextLabel::get_text); ObjectTypeDB::bind_method(_MD("add_text","text"),&RichTextLabel::add_text); ObjectTypeDB::bind_method(_MD("add_image","image:Texture"),&RichTextLabel::add_image); ObjectTypeDB::bind_method(_MD("newline"),&RichTextLabel::add_newline); diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index 635fe87ad4..5147905a0e 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -280,6 +280,7 @@ protected: public: + String get_text(); void add_text(const String& p_text); void add_image(const Ref<Texture>& p_image); void add_newline(); diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index 9bf93aff77..190e8e141f 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -177,7 +177,6 @@ void ScrollContainer::_input_event(const InputEvent& p_input_event) { void ScrollContainer::_update_scrollbar_pos() { - Size2 size = get_size(); Size2 hmin = h_scroll->get_combined_minimum_size(); Size2 vmin = v_scroll->get_combined_minimum_size(); diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 5eb579f1d2..0e0339c488 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -40,8 +40,6 @@ int TabContainer::_get_top_margin() const { int h = MAX( tab_bg->get_minimum_size().height,tab_fg->get_minimum_size().height); -// h+=MIN( get_constant("label_valign_fg"), get_constant("label_valign_bg") ); - int ch = font->get_height();; for(int i=0;i<get_child_count();i++) { @@ -207,9 +205,7 @@ void TabContainer::_notification(int p_what) { Ref<StyleBox> tab_bg = get_stylebox("tab_bg"); Ref<StyleBox> tab_fg = get_stylebox("tab_fg"); Ref<Texture> incr = get_icon("increment"); - Ref<Texture> incr_hl = get_icon("increment_hilite"); Ref<Texture> decr = get_icon("decrement"); - Ref<Texture> decr_hl = get_icon("decrement_hilite"); Ref<Texture> menu = get_icon("menu"); Ref<Texture> menu_hl = get_icon("menu_hl"); Ref<Font> font = get_font("font"); @@ -219,9 +215,6 @@ void TabContainer::_notification(int p_what) { int side_margin = get_constant("side_margin"); int top_margin = _get_top_margin(); - int label_valign_fg = get_constant("label_valign_fg"); - int label_valign_bg = get_constant("label_valign_bg"); - Size2 top_size = Size2( size.width, top_margin ); @@ -338,17 +331,14 @@ void TabContainer::_notification(int p_what) { Ref<StyleBox> sb; - int va; Color col; if (idx==current) { sb=tab_fg; - va=label_valign_fg; col=color_fg; } else { sb=tab_bg; - va=label_valign_bg; col=color_bg; } @@ -371,23 +361,7 @@ void TabContainer::_notification(int p_what) { } font->draw(ci, Point2i( lpos.x, sb->get_margin(MARGIN_TOP)+((sb_rect.size.y-sb_ms.y)-font->get_height())/2+font->get_ascent() ), s, col ); - //ofs+=sb_ms.x+w; - - /* - int sb_mw = sb->get_minimum_size().width; - int font_ofs = sb_mw / 2; - - Rect2i rect =Rect2( ofs, 0, w+sb_mw, top_margin); - rect.size - sb->draw(ci,rect); - rect.y+=va; - rect.height+=va; - int font_y = (rect.height - font->get_height())/2; - - font->draw(ci, Point2( ofs+font_ofs, va+font_y ), s, col ); - -*/ idx++; } @@ -477,7 +451,6 @@ void TabContainer::set_current_tab(int p_current) { ERR_FAIL_INDEX( p_current, get_tab_count() ); - //printf("DEBUG %p: set_current_tab to %i\n", this, p_current); current=p_current; int idx=0; @@ -560,7 +533,6 @@ Control* TabContainer::get_current_tab_control() const { void TabContainer::remove_child_notify(Node *p_child) { int tc = get_tab_count(); -// bool set_curent=false; if (current==tc-1) { current--; if (current<0) @@ -705,9 +677,6 @@ Size2 TabContainer::get_minimum_size() const { if (c->is_set_as_toplevel()) continue; - //if (!c->has_meta("_tab_name")) - // continue; - if (!c->is_visible()) continue; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 6fd6137ac8..af04fbd201 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -852,6 +852,11 @@ void TextEdit::_notification(int p_what) { k++; } + // check for space between name and bracket + while (k < str.length() && (str[k] == '\t' || str[k] == ' ')) { + k++; + } + if (str[k] == '(') { in_function_name = true; } @@ -960,6 +965,12 @@ void TextEdit::_notification(int p_what) { } bool in_highlighted_word = (j >= highlighted_text_col && j < highlighted_text_col+highlighted_text.length()); + + /* if this is the original highlighted text we don't want to highlight it again */ + if (cursor.line==line && (cursor.column >= highlighted_text_col && cursor.column <= highlighted_text_col+highlighted_text.length())) { + in_highlighted_word = false; + } + if (in_highlighted_word) { VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin, ofs_y ), Size2i(char_w, get_row_height())),cache.word_highlighted_color); } @@ -988,34 +999,39 @@ void TextEdit::_notification(int p_what) { } } - - if (str[j]>=32) - cache.font->draw_char(ci,Point2i( char_ofs+char_margin, ofs_y+ascent),str[j],str[j+1],in_selection?cache.font_selected_color:color); - - else if (draw_tabs && str[j]=='\t') { - int yofs= (get_row_height() - cache.tab_icon->get_height())/2; - cache.tab_icon->draw(ci, Point2(char_ofs+char_margin,ofs_y+yofs),in_selection?cache.font_selected_color:color); - } - - if (cursor.column==j && cursor.line==line) { cursor_pos = Point2i( char_ofs+char_margin, ofs_y ); if (insert_mode) { - cursor_pos.y += get_row_height(); + cursor_pos.y += (get_row_height() - 3); } + int caret_w = (str[j]=='\t') ? cache.font->get_char_size(' ').width : char_w; if (draw_caret) { if (insert_mode) { - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(char_w,1)),cache.caret_color); + int caret_h = (block_caret) ? 4 : 1; + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(caret_w,caret_h)),cache.caret_color); } else { - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(1,get_row_height())),cache.caret_color); + caret_w = (block_caret) ? caret_w : 1; + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(caret_w,get_row_height())),cache.caret_color); } } } - char_ofs+=char_w; + if (cursor.column==j && cursor.line==line && block_caret && draw_caret && !insert_mode) { + color = cache.caret_background_color; + } + + if (str[j]>=32) + cache.font->draw_char(ci,Point2i( char_ofs+char_margin, ofs_y+ascent),str[j],str[j+1],in_selection?cache.font_selected_color:color); + + else if (draw_tabs && str[j]=='\t') { + int yofs= (get_row_height() - cache.tab_icon->get_height())/2; + cache.tab_icon->draw(ci, Point2(char_ofs+char_margin,ofs_y+yofs),in_selection?cache.font_selected_color:color); + } + + char_ofs+=char_w; } if (cursor.column==str.length() && cursor.line==line && (char_ofs+char_margin)>=xmargin_beg) { @@ -1023,15 +1039,18 @@ void TextEdit::_notification(int p_what) { cursor_pos=Point2i( char_ofs+char_margin, ofs_y ); if (insert_mode) { - cursor_pos.y += get_row_height(); + cursor_pos.y += (get_row_height() - 3); } if (draw_caret) { if (insert_mode) { int char_w = cache.font->get_char_size(' ').width; - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(char_w,1)),cache.caret_color); + int caret_h = (block_caret) ? 4 : 1; + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(char_w,caret_h)),cache.caret_color); } else { - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(1,get_row_height())),cache.caret_color); + int char_w = cache.font->get_char_size(' ').width; + int caret_w = (block_caret) ? char_w : 1; + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(caret_w,get_row_height())),cache.caret_color); } } } @@ -1100,7 +1119,7 @@ void TextEdit::_notification(int p_what) { int l = line_from + i; ERR_CONTINUE( l < 0 || l>= completion_options.size()); - Color text_color = cache.font_color; + Color text_color = cache.completion_font_color; for(int j=0;j<color_regions.size();j++) { if (completion_options[l].begins_with(color_regions[j].begin_key)) { text_color=color_regions[j].color; @@ -1491,6 +1510,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { int gutter=cache.style_normal->get_margin(MARGIN_LEFT); if (mb.x > gutter && mb.x <= gutter + cache.breakpoint_gutter_width + 3) { set_line_as_breakpoint(row, !is_line_set_as_breakpoint(row)); + emit_signal("breakpoint_toggled", row); return; } } @@ -1973,6 +1993,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } } break; case KEY_TAB: { + if (k.mod.command) break; // avoid tab when command if (readonly) break; @@ -2972,6 +2993,34 @@ void TextEdit::adjust_viewport_to_cursor() { } +void TextEdit::center_viewport_to_cursor() { + + if (cursor.line_ofs>cursor.line) + cursor.line_ofs=cursor.line; + + int visible_width=cache.size.width-cache.style_normal->get_minimum_size().width-cache.line_number_w-cache.breakpoint_gutter_width; + if (v_scroll->is_visible()) + visible_width-=v_scroll->get_combined_minimum_size().width; + visible_width-=20; // give it a little more space + + int visible_rows = get_visible_rows(); + if (h_scroll->is_visible()) + visible_rows-=((h_scroll->get_combined_minimum_size().height-1)/get_row_height()); + + int max_ofs = text.size()-(scroll_past_end_of_file_enabled?1:visible_rows); + cursor.line_ofs=CLAMP(cursor.line-(visible_rows/2),0,max_ofs); + + int cursor_x = get_column_x_offset( cursor.column, text[cursor.line] ); + + if (cursor_x>(cursor.x_ofs+visible_width)) + cursor.x_ofs=cursor_x-visible_width+1; + + if (cursor_x < cursor.x_ofs) + cursor.x_ofs=cursor_x; + + update(); +} + void TextEdit::cursor_set_column(int p_col, bool p_adjust_viewport) { if (p_col<0) @@ -3062,6 +3111,15 @@ void TextEdit::cursor_set_blink_speed(const float p_speed) { caret_blink_timer->set_wait_time(p_speed); } +void TextEdit::cursor_set_block_mode(const bool p_enable){ + block_caret = p_enable; + update(); +} + +bool TextEdit::cursor_is_block_mode() const { + return block_caret; +} + void TextEdit::_scroll_moved(double p_to_val) { @@ -3300,8 +3358,10 @@ void TextEdit::_update_caches() { cache.completion_background_color=get_color("completion_background_color"); cache.completion_selected_color=get_color("completion_selected_color"); cache.completion_existing_color=get_color("completion_existing_color"); + cache.completion_font_color=get_color("completion_font_color"); cache.font=get_font("font"); cache.caret_color=get_color("caret_color"); + cache.caret_background_color=get_color("caret_background_color"); cache.line_number_color=get_color("line_number_color"); cache.font_color=get_color("font_color"); cache.font_selected_color=get_color("font_selected_color"); @@ -3597,6 +3657,10 @@ void TextEdit::set_highlight_all_occurrences(const bool p_enabled) { update(); } +bool TextEdit::is_highlight_all_occurrences_enabled() const { + return highlight_all_occurrences; +} + int TextEdit::_get_column_pos_of_word(const String &p_key, const String &p_search, uint32_t p_search_flags, int p_from_column) { int col = -1; @@ -4116,7 +4180,7 @@ void TextEdit::_update_completion_candidates() { } } - if (l[cursor.column - 1] == '(' && !pre_keyword && !completion_strings[0].begins_with("\"")) { + if (cursor.column > 0 && l[cursor.column - 1] == '(' && !pre_keyword && !completion_strings[0].begins_with("\"")) { cancel = true; } @@ -4131,16 +4195,28 @@ void TextEdit::_update_completion_candidates() { completion_options.clear(); completion_index=0; completion_base=s; - int ci_match=0; Vector<float> sim_cache; for(int i=0;i<completion_strings.size();i++) { + if (s == completion_strings[i]) { + // A perfect match, stop completion + _cancel_completion(); + return; + } if (s.is_subsequence_ofi(completion_strings[i])) { // don't remove duplicates if no input is provided if (s != "" && completion_options.find(completion_strings[i]) != -1) { continue; } // Calculate the similarity to keep completions in good order - float similarity = s.similarity(completion_strings[i]); + float similarity; + if (completion_strings[i].to_lower().begins_with(s.to_lower())) { + // Substrings are the best candidates + similarity = 1.1; + } else { + // Otherwise compute the similarity + similarity = s.to_lower().similarity(completion_strings[i].to_lower()); + } + int comp_size = completion_options.size(); if (comp_size == 0) { completion_options.push_back(completion_strings[i]); @@ -4150,8 +4226,8 @@ void TextEdit::_update_completion_candidates() { int pos = 0; do { comp_sim = sim_cache[pos++]; - } while(pos < comp_size && similarity <= comp_sim); - pos--; // Pos will be off by one + } while(pos < comp_size && similarity < comp_sim); + pos = similarity > comp_sim ? pos - 1 : pos; // Pos will be off by one completion_options.insert(pos, completion_strings[i]); sim_cache.insert(pos, similarity); } @@ -4294,6 +4370,10 @@ void TextEdit::set_show_line_numbers(bool p_show) { update(); } +bool TextEdit::is_show_line_numbers_enabled() const { + return line_numbers; +} + void TextEdit::set_draw_breakpoint_gutter(bool p_draw) { draw_breakpoint_gutter = p_draw; update(); @@ -4384,6 +4464,8 @@ void TextEdit::_bind_methods() { ObjectTypeDB::bind_method(_MD("cursor_get_blink_enabled"),&TextEdit::cursor_get_blink_enabled); ObjectTypeDB::bind_method(_MD("cursor_set_blink_speed", "blink_speed"),&TextEdit::cursor_set_blink_speed); ObjectTypeDB::bind_method(_MD("cursor_get_blink_speed"),&TextEdit::cursor_get_blink_speed); + ObjectTypeDB::bind_method(_MD("cursor_set_block_mode", "enable"), &TextEdit::cursor_set_block_mode); + ObjectTypeDB::bind_method(_MD("cursor_is_block_mode"), &TextEdit::cursor_is_block_mode); ObjectTypeDB::bind_method(_MD("set_readonly","enable"),&TextEdit::set_readonly); ObjectTypeDB::bind_method(_MD("set_wrap","enable"),&TextEdit::set_wrap); @@ -4408,6 +4490,12 @@ void TextEdit::_bind_methods() { ObjectTypeDB::bind_method(_MD("redo"),&TextEdit::redo); ObjectTypeDB::bind_method(_MD("clear_undo_history"),&TextEdit::clear_undo_history); + ObjectTypeDB::bind_method(_MD("set_show_line_numbers", "enable"), &TextEdit::set_show_line_numbers); + ObjectTypeDB::bind_method(_MD("is_show_line_numbers_enabled"), &TextEdit::is_show_line_numbers_enabled); + + ObjectTypeDB::bind_method(_MD("set_highlight_all_occurrences", "enable"), &TextEdit::set_highlight_all_occurrences); + ObjectTypeDB::bind_method(_MD("is_highlight_all_occurrences_enabled"), &TextEdit::is_highlight_all_occurrences_enabled); + ObjectTypeDB::bind_method(_MD("set_syntax_coloring","enable"),&TextEdit::set_syntax_coloring); ObjectTypeDB::bind_method(_MD("is_syntax_coloring_enabled"),&TextEdit::is_syntax_coloring_enabled); @@ -4420,12 +4508,17 @@ void TextEdit::_bind_methods() { ObjectTypeDB::bind_method(_MD("menu_option"),&TextEdit::menu_option); ObjectTypeDB::bind_method(_MD("get_menu:PopupMenu"),&TextEdit::get_menu); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret/caret_blink"), _SCS("cursor_set_blink_enabled"), _SCS("cursor_get_blink_enabled"));; + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_line_numbers"), _SCS("set_show_line_numbers"), _SCS("is_show_line_numbers_enabled")); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_all_occurrences"), _SCS("set_highlight_all_occurrences"), _SCS("is_highlight_all_occurrences_enabled")); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret/block_caret"), _SCS("cursor_set_block_mode"), _SCS("cursor_is_block_mode")); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret/caret_blink"), _SCS("cursor_set_blink_enabled"), _SCS("cursor_get_blink_enabled")); ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "caret/caret_blink_speed",PROPERTY_HINT_RANGE,"0.1,10,0.1"), _SCS("cursor_set_blink_speed"),_SCS("cursor_get_blink_speed") ); ADD_SIGNAL(MethodInfo("cursor_changed")); ADD_SIGNAL(MethodInfo("text_changed")); ADD_SIGNAL(MethodInfo("request_completion")); + ADD_SIGNAL(MethodInfo("breakpoint_toggled", PropertyInfo( Variant::INT, "row"))); BIND_CONSTANT( MENU_CUT ); BIND_CONSTANT( MENU_COPY ); @@ -4485,6 +4578,7 @@ TextEdit::TextEdit() { selection.active=false; syntax_coloring=false; + block_caret=false; caret_blink_enabled=false; caret_blink_timer = memnew(Timer); add_child(caret_blink_timer); @@ -4541,6 +4635,7 @@ TextEdit::TextEdit() { scroll_past_end_of_file_enabled=false; auto_brace_completion_enabled=false; brace_matching_enabled=false; + highlight_all_occurrences=false; auto_indent=false; insert_mode = false; window_has_focus=true; diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index acac687b59..c3bdf7c856 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -77,7 +77,9 @@ class TextEdit : public Control { Color completion_background_color; Color completion_selected_color; Color completion_existing_color; + Color completion_font_color; Color caret_color; + Color caret_background_color; Color line_number_color; Color font_color; Color font_selected_color; @@ -221,6 +223,7 @@ class TextEdit : public Control { bool caret_blink_enabled; bool draw_caret; bool window_has_focus; + bool block_caret; bool setting_row; bool wrap; @@ -393,6 +396,8 @@ public: } void set_auto_indent(bool p_auto_indent); + void center_viewport_to_cursor(); + void cursor_set_column(int p_col, bool p_adjust_viewport=true); void cursor_set_line(int p_row, bool p_adjust_viewport=true); @@ -405,6 +410,9 @@ public: float cursor_get_blink_speed() const; void cursor_set_blink_speed(const float p_speed); + void cursor_set_block_mode(const bool p_enable); + bool cursor_is_block_mode() const; + void set_readonly(bool p_readonly); void set_max_chars(int p_max_chars); @@ -427,6 +435,7 @@ public: void set_current_search_result(int line, int col); void set_highlight_all_occurrences(const bool p_enabled); + bool is_highlight_all_occurrences_enabled() const; bool is_selection_active() const; int get_selection_from_line() const; int get_selection_from_column() const; @@ -468,6 +477,7 @@ public: void menu_option(int p_option); void set_show_line_numbers(bool p_show); + bool is_show_line_numbers_enabled() const; void set_draw_breakpoint_gutter(bool p_draw); bool is_drawing_breakpoint_gutter() const; diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp index c885b2d73e..df2f5edd48 100644 --- a/scene/gui/texture_button.cpp +++ b/scene/gui/texture_button.cpp @@ -76,10 +76,7 @@ void TextureButton::_notification(int p_what) { switch( p_what ) { case NOTIFICATION_DRAW: { - RID canvas_item = get_canvas_item(); DrawMode draw_mode = get_draw_mode(); -// if (normal.is_null()) -// break; Ref<Texture> texdraw; diff --git a/scene/gui/texture_frame.cpp b/scene/gui/texture_frame.cpp index 143f0e83b8..4aa45af863 100644 --- a/scene/gui/texture_frame.cpp +++ b/scene/gui/texture_frame.cpp @@ -37,9 +37,6 @@ void TextureFrame::_notification(int p_what) { return; - - RID ci = get_canvas_item(); - switch(stretch_mode) { case STRETCH_SCALE_ON_EXPAND: { Size2 s=expand?get_size():texture->get_size(); @@ -85,23 +82,6 @@ void TextureFrame::_notification(int p_what) { } - -/* - Vector<Point2> points; - points.resize(4); - points[0]=Point2(0,0); - points[1]=Point2(s.x,0); - points[2]=Point2(s.x,s.y); - points[3]=Point2(0,s.y); - Vector<Point2> uvs; - uvs.resize(4); - uvs[0]=Point2(0,0); - uvs[1]=Point2(1,0); - uvs[2]=Point2(1,1); - uvs[3]=Point2(0,1); - - VisualServer::get_singleton()->canvas_item_add_primitive(ci,points,Vector<Color>(),uvs,texture->get_rid()); -*/ } } diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index f8516f8f5d..82459ba0ab 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -693,6 +693,7 @@ void TreeItem::_bind_methods() { ObjectTypeDB::bind_method(_MD("add_button","column","button:Texture","button_idx","disabled"),&TreeItem::add_button,DEFVAL(-1),DEFVAL(false)); ObjectTypeDB::bind_method(_MD("get_button_count","column"),&TreeItem::get_button_count); ObjectTypeDB::bind_method(_MD("get_button:Texture","column","button_idx"),&TreeItem::get_button); + ObjectTypeDB::bind_method(_MD("set_button","column","button_idx","button:Texture"),&TreeItem::set_button); ObjectTypeDB::bind_method(_MD("erase_button","column","button_idx"),&TreeItem::erase_button); ObjectTypeDB::bind_method(_MD("is_button_disabled","column","button_idx"),&TreeItem::is_button_disabled); @@ -973,22 +974,12 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2& /* Draw label, if height fits */ - Point2i guide_from; bool skip=(p_item==root && hide_root); - // printf("skip (%p == %p && %i) %i\n",p_item,root,hide_root,skip); if (!skip && (p_pos.y+label_h-cache.offset.y)>0) { - // printf("entering\n"); - - int height=label_h; - - Point2i guide_space=Point2i( cache.guide_width , height ); - - - if (!hide_folding && p_item->childs) { //has childs, draw the guide box Ref<Texture> arrow; @@ -1040,7 +1031,7 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2& Point2i o = Point2i( ofs+w-s.width, p_pos.y )-cache.offset+p_draw_ofs; - if (cache.click_type==Cache::CLICK_BUTTON && cache.click_item==p_item && cache.click_column==i && !p_item->cells[i].buttons[j].disabled) { + if (cache.click_type==Cache::CLICK_BUTTON && cache.click_item==p_item && cache.click_column==i && cache.click_index==j && !p_item->cells[i].buttons[j].disabled) { //being pressed cache.button_pressed->draw(get_canvas_item(),Rect2(o,s)); } @@ -1345,7 +1336,7 @@ int Tree::_count_selected_items(TreeItem* p_from) const { return count; } -void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col,TreeItem *p_prev,bool *r_in_range) { +void Tree::select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_col, TreeItem *p_prev, bool *r_in_range, bool p_force_deselect) { TreeItem::Cell &selected_cell=p_selected->cells[p_col]; @@ -1355,6 +1346,8 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col switched=true; } + bool emitted_row=false; + for (int i=0;i<columns.size();i++) { TreeItem::Cell &c=p_current->cells[i]; @@ -1373,7 +1366,10 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col selected_item=p_selected; selected_col=0; selected_item=p_selected; - emit_signal("item_selected"); + if (!emitted_row) { + emit_signal("item_selected"); + emitted_row=true; + } //if (p_col==i) // p_current->selected_signal.call(p_col); } @@ -1414,7 +1410,7 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col } else { - if (r_in_range && *r_in_range) { + if (r_in_range && *r_in_range && !p_force_deselect) { if (!c.selected && c.selectable) { @@ -1422,7 +1418,7 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col emit_signal("multi_selected",p_current,i,true); } - } else if (!r_in_range){ + } else if (!r_in_range || p_force_deselect){ if (select_mode==SELECT_MULTI && c.selected) emit_signal("multi_selected",p_current,i,false); c.selected=false; @@ -1441,7 +1437,7 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col while (c) { - select_single_item(p_selected,c,p_col,p_prev,r_in_range); + select_single_item(p_selected,c,p_col,p_prev,r_in_range,p_current->is_collapsed() || p_force_deselect); c=c->next; } @@ -1655,7 +1651,6 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ /* editing */ bool bring_up_editor=force_select_on_already_selected ? (c.selected && already_selected) : c.selected; - bool bring_up_value_editor=false; String editor_text=c.text; switch (c.mode) { @@ -1706,9 +1701,6 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ bring_up_editor=false; } else { - Ref<Texture> updown = cache.updown; - - if (x >= (col_width-item_h/2)) { /* touching the combo */ @@ -1755,7 +1747,6 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ } else { editor_text=String::num( p_item->cells[col].val, Math::decimals( p_item->cells[col].step ) ); - bring_up_value_editor=false; if (select_mode==SELECT_MULTI && get_tree()->get_last_event_id() == focus_in_id) bring_up_editor=false; @@ -2274,7 +2265,7 @@ void Tree::_input_event(InputEvent p_event) { update(); } - if (pressing_for_editor && popup_edited_item && popup_edited_item->get_cell_mode(popup_edited_item_col)==TreeItem::CELL_MODE_RANGE) { + if (pressing_for_editor && popup_edited_item && (popup_edited_item->get_cell_mode(popup_edited_item_col)==TreeItem::CELL_MODE_RANGE || popup_edited_item->get_cell_mode(popup_edited_item_col)==TreeItem::CELL_MODE_RANGE_EXPRESSION)) { //range drag if (!range_drag_enabled) { diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 0172546c1d..f5100ab5b6 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -331,7 +331,7 @@ friend class TreeItem; // 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); 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); + 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 InputModifierState& p_mod); void text_editor_enter(String p_text); void _text_editor_modal_close(); diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp index e9ff76bd91..1be847929d 100644 --- a/scene/gui/video_player.cpp +++ b/scene/gui/video_player.cpp @@ -116,7 +116,6 @@ void VideoPlayer::_notification(int p_notification) { case NOTIFICATION_ENTER_TREE: { - //set_idle_process(false); //don't annoy if (stream.is_valid() && autoplay && !get_tree()->is_editor_hint()) { play(); } @@ -141,13 +140,6 @@ void VideoPlayer::_notification(int p_notification) { playback->update(delta); - /*int prev_width = texture->get_width(); - stream->pop_frame(texture); - if (prev_width == 0) { - update(); - minimum_size_changed(); - };*/ - } break; case NOTIFICATION_DRAW: { @@ -158,8 +150,6 @@ void VideoPlayer::_notification(int p_notification) { return; Size2 s=expand?get_size():texture->get_size(); - RID ci = get_canvas_item(); - printf("drawing with size %f, %f\n", s.x, s.y); draw_texture_rect(texture,Rect2(Point2(),s),false); } break; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 11b400d4a9..a53c19d2e7 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -1121,6 +1121,38 @@ Node *Node::get_owner() const { return data.owner; } + +Node* Node::find_common_parent_with(const Node *p_node) const { + + if (this==p_node) + return const_cast<Node*>(p_node); + + Set<const Node*> visited; + + const Node *n=this; + + while(n) { + + visited.insert(n); + n=n->data.parent; + } + + const Node *common_parent=p_node; + + while(common_parent) { + + if (visited.has(common_parent)) + break; + common_parent=common_parent->data.parent; + } + + if (!common_parent) + return NULL; + + return const_cast<Node*>(common_parent); + +} + NodePath Node::get_path_to(const Node *p_node) const { ERR_FAIL_NULL_V(p_node,NodePath()); @@ -1206,7 +1238,6 @@ void Node::add_to_group(const StringName& p_identifier,bool p_persistent) { GroupData gd; - SceneTree::Group *gptr=NULL; if (data.tree) { gd.group=data.tree->add_to_group(p_identifier,this); } else { @@ -1513,7 +1544,7 @@ int Node::get_position_in_parent() const { -Node *Node::duplicate(bool p_use_instancing) const { +Node *Node::_duplicate(bool p_use_instancing) const { Node *node=NULL; @@ -1592,9 +1623,21 @@ Node *Node::duplicate(bool p_use_instancing) const { node->add_child(dup); } + return node; } +Node *Node::duplicate(bool p_use_instancing) const { + + Node* dupe = _duplicate(p_use_instancing); + + if (dupe) { + _duplicate_signals(this,dupe); + } + + return dupe; +} + void Node::_duplicate_and_reown(Node* p_new_parent, const Map<Node*,Node*>& p_reown_map) const { @@ -1664,12 +1707,13 @@ void Node::_duplicate_and_reown(Node* p_new_parent, const Map<Node*,Node*>& p_re void Node::_duplicate_signals(const Node* p_original,Node* p_copy) const { - if (this!=p_original && get_owner()!=p_original) + if (this!=p_original && (get_owner()!=p_original && get_owner()!=p_original->get_owner())) return; List<Connection> conns; get_all_signal_connections(&conns); + for (List<Connection>::Element *E=conns.front();E;E=E->next()) { if (E->get().flags&CONNECT_PERSIST) { @@ -1678,14 +1722,17 @@ void Node::_duplicate_signals(const Node* p_original,Node* p_copy) const { Node *copy = p_copy->get_node(p); Node *target = E->get().target->cast_to<Node>(); - if (!target) + if (!target) { continue; + } NodePath ptarget = p_original->get_path_to(target); Node *copytarget = p_copy->get_node(ptarget); + if (copy && copytarget) { copy->connect(E->get().signal,copytarget,E->get().method,E->get().binds,CONNECT_PERSIST); } + } } @@ -2085,6 +2132,15 @@ bool Node::is_owned_by_parent() const { return data.parent_owned; } +void Node::set_display_folded(bool p_folded) { + data.display_folded=p_folded; +} + +bool Node::is_displayed_folded() const { + + return data.display_folded; +} + void Node::_bind_methods() { ObjectTypeDB::bind_method(_MD("_add_child_below_node","node:Node","child_node:Node","legible_unique_name"),&Node::add_child_below_node,DEFVAL(false)); @@ -2140,6 +2196,8 @@ void Node::_bind_methods() { ObjectTypeDB::bind_method(_MD("can_process"),&Node::can_process); ObjectTypeDB::bind_method(_MD("print_stray_nodes"),&Node::_print_stray_nodes); ObjectTypeDB::bind_method(_MD("get_position_in_parent"),&Node::get_position_in_parent); + ObjectTypeDB::bind_method(_MD("set_display_folded","fold"),&Node::set_display_folded); + ObjectTypeDB::bind_method(_MD("is_displayed_folded"),&Node::is_displayed_folded); ObjectTypeDB::bind_method(_MD("get_tree:SceneTree"),&Node::get_tree); @@ -2194,6 +2252,7 @@ void Node::_bind_methods() { //ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "process/input" ), _SCS("set_process_input"),_SCS("is_processing_input" ) ); //ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "process/unhandled_input" ), _SCS("set_process_unhandled_input"),_SCS("is_processing_unhandled_input" ) ); ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "process/pause_mode",PROPERTY_HINT_ENUM,"Inherit,Stop,Process" ), _SCS("set_pause_mode"),_SCS("get_pause_mode" ) ); + ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "editor/display_folded",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR ), _SCS("set_display_folded"),_SCS("is_displayed_folded" ) ); BIND_VMETHOD( MethodInfo("_process",PropertyInfo(Variant::REAL,"delta")) ); BIND_VMETHOD( MethodInfo("_fixed_process",PropertyInfo(Variant::REAL,"delta")) ); @@ -2231,6 +2290,7 @@ Node::Node() { data.in_constructor=true; data.viewport=NULL; data.use_placeholder=false; + data.display_folded=false; } Node::~Node() { @@ -2240,6 +2300,7 @@ Node::~Node() { data.owned.clear(); data.children.clear(); + ERR_FAIL_COND(data.parent); ERR_FAIL_COND(data.children.size()); diff --git a/scene/main/node.h b/scene/main/node.h index 88334f32f0..18e403cd61 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -111,6 +111,7 @@ private: bool in_constructor; bool use_placeholder; + bool display_folded; } data; @@ -137,6 +138,8 @@ private: void _duplicate_signals(const Node* p_original,Node* p_copy) const; void _duplicate_and_reown(Node* p_new_parent, const Map<Node*,Node*>& p_reown_map) const; + Node *_duplicate(bool p_use_instancing) const; + Array _get_children() const; Array _get_groups() const; @@ -212,6 +215,7 @@ public: NodePath get_path() const; NodePath get_path_to(const Node *p_node) const; + Node* find_common_parent_with(const Node *p_node) const; void add_to_group(const StringName& p_identifier,bool p_persistent=false); void remove_from_group(const StringName& p_identifier); @@ -325,6 +329,8 @@ public: void update_configuration_warning(); + void set_display_folded(bool p_folded); + bool is_displayed_folded() const; /* CANVAS */ Node(); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 3c52af1c1e..bdb2754e5e 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -1083,7 +1083,7 @@ void Viewport::_propagate_exit_world(Node *p_node) { Spatial *s = p_node->cast_to<Spatial>(); if (s) { - s->notification(Spatial::NOTIFICATION_EXIT_WORLD,false); + s->notification(Spatial::NOTIFICATION_EXIT_WORLD, true); } else { Viewport *v = p_node->cast_to<Viewport>(); if (v) { @@ -1331,11 +1331,11 @@ Matrix32 Viewport::_get_input_pre_xform() const { Matrix32 pre_xf; if (render_target) { - ERR_FAIL_COND_V(to_screen_rect.size.x==0,pre_xf); - ERR_FAIL_COND_V(to_screen_rect.size.y==0,pre_xf); + if (to_screen_rect!=Rect2()) { - pre_xf.elements[2]=-to_screen_rect.pos; - pre_xf.scale(rect.size/to_screen_rect.size); + pre_xf.elements[2]=-to_screen_rect.pos; + pre_xf.scale(rect.size/to_screen_rect.size); + } } else { pre_xf.elements[2]=-rect.pos; @@ -1346,13 +1346,21 @@ Matrix32 Viewport::_get_input_pre_xform() const { void Viewport::_make_input_local(InputEvent& ev) { + switch(ev.type) { case InputEvent::MOUSE_BUTTON: { + Vector2 vp_ofs; + if (parent_control) { + vp_ofs = (parent_control->get_viewport()->get_final_transform() * parent_control->get_global_transform_with_canvas()).get_origin(); + } + Matrix32 ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); Vector2 g = ai.xform(Vector2(ev.mouse_button.global_x,ev.mouse_button.global_y)); - Vector2 l = ai.xform(Vector2(ev.mouse_button.x,ev.mouse_button.y)); + Vector2 l = ai.xform(Vector2(ev.mouse_button.x,ev.mouse_button.y)-vp_ofs); + + ev.mouse_button.x=l.x; ev.mouse_button.y=l.y; ev.mouse_button.global_x=g.x; @@ -1361,11 +1369,18 @@ void Viewport::_make_input_local(InputEvent& ev) { } break; case InputEvent::MOUSE_MOTION: { + Vector2 vp_ofs; + if (parent_control) { + vp_ofs = (parent_control->get_viewport()->get_final_transform() * parent_control->get_global_transform_with_canvas()).get_origin(); + } + Matrix32 ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); Vector2 g = ai.xform(Vector2(ev.mouse_motion.global_x,ev.mouse_motion.global_y)); - Vector2 l = ai.xform(Vector2(ev.mouse_motion.x,ev.mouse_motion.y)); + Vector2 l = ai.xform(Vector2(ev.mouse_motion.x,ev.mouse_motion.y)-vp_ofs); Vector2 r = ai.basis_xform(Vector2(ev.mouse_motion.relative_x,ev.mouse_motion.relative_y)); Vector2 s = ai.basis_xform(Vector2(ev.mouse_motion.speed_x,ev.mouse_motion.speed_y)); + + ev.mouse_motion.x=l.x; ev.mouse_motion.y=l.y; ev.mouse_motion.global_x=g.x; @@ -1378,16 +1393,28 @@ void Viewport::_make_input_local(InputEvent& ev) { } break; case InputEvent::SCREEN_TOUCH: { + Vector2 vp_ofs; + if (parent_control) { + vp_ofs = (parent_control->get_viewport()->get_final_transform() * parent_control->get_global_transform_with_canvas()).get_origin(); + } + Matrix32 ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); - Vector2 t = ai.xform(Vector2(ev.screen_touch.x,ev.screen_touch.y)); + Vector2 t = ai.xform(Vector2(ev.screen_touch.x,ev.screen_touch.y)-vp_ofs); + + ev.screen_touch.x=t.x; ev.screen_touch.y=t.y; } break; case InputEvent::SCREEN_DRAG: { + Vector2 vp_ofs; + if (parent_control) { + vp_ofs = (parent_control->get_viewport()->get_final_transform() * parent_control->get_global_transform_with_canvas()).get_origin(); + } + Matrix32 ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); - Vector2 t = ai.xform(Vector2(ev.screen_drag.x,ev.screen_drag.y)); + Vector2 t = ai.xform(Vector2(ev.screen_drag.x,ev.screen_drag.y)-vp_ofs); Vector2 r = ai.basis_xform(Vector2(ev.screen_drag.relative_x,ev.screen_drag.relative_y)); Vector2 s = ai.basis_xform(Vector2(ev.screen_drag.speed_x,ev.screen_drag.speed_y)); ev.screen_drag.x=t.x; @@ -1575,35 +1602,38 @@ void Viewport::_gui_call_input(Control *p_control,const InputEvent& p_input) { // _block(); + InputEvent ev = p_input; + //mouse wheel events can't be stopped - bool cant_stop_me_now = (p_input.type==InputEvent::MOUSE_BUTTON && - (p_input.mouse_button.button_index==BUTTON_WHEEL_DOWN || - p_input.mouse_button.button_index==BUTTON_WHEEL_UP || - p_input.mouse_button.button_index==BUTTON_WHEEL_LEFT || - p_input.mouse_button.button_index==BUTTON_WHEEL_RIGHT ) ); + bool cant_stop_me_now = (ev.type==InputEvent::MOUSE_BUTTON && + (ev.mouse_button.button_index==BUTTON_WHEEL_DOWN || + ev.mouse_button.button_index==BUTTON_WHEEL_UP || + ev.mouse_button.button_index==BUTTON_WHEEL_LEFT || + ev.mouse_button.button_index==BUTTON_WHEEL_RIGHT ) ); CanvasItem *ci=p_control; while(ci) { Control *control = ci->cast_to<Control>(); if (control) { - control->call_multilevel(SceneStringNames::get_singleton()->_input_event,p_input); + control->call_multilevel(SceneStringNames::get_singleton()->_input_event,ev); if (gui.key_event_accepted) break; if (!control->is_inside_tree()) break; - control->emit_signal(SceneStringNames::get_singleton()->input_event,p_input); + control->emit_signal(SceneStringNames::get_singleton()->input_event,ev); if (!control->is_inside_tree() || control->is_set_as_toplevel()) break; if (gui.key_event_accepted) break; - if (!cant_stop_me_now && control->data.stop_mouse && (p_input.type==InputEvent::MOUSE_BUTTON || p_input.type==InputEvent::MOUSE_MOTION)) + if (!cant_stop_me_now && control->data.stop_mouse && (ev.type==InputEvent::MOUSE_BUTTON || ev.type==InputEvent::MOUSE_MOTION)) break; } if (ci->is_set_as_toplevel()) break; + ev=ev.xform_by(ci->get_transform()); //transform event upwards ci=ci->get_parent_item(); } @@ -1749,8 +1779,9 @@ void Viewport::_gui_input_event(InputEvent p_event) { Vector2 pos = top->get_global_transform_with_canvas().affine_inverse().xform(mpos); if (!top->has_point(pos)) { - if (top->data.modal_exclusive) { + if (top->data.modal_exclusive || top->data.modal_frame==OS::get_singleton()->get_frames_drawn()) { //cancel event, sorry, modal exclusive EATS UP ALL + //alternative, you can't pop out a window the same frame it was made modal (fixes many issues) //get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID); get_tree()->set_input_as_handled(); return; // no one gets the event if exclusive NO ONE @@ -1784,15 +1815,12 @@ void Viewport::_gui_input_event(InputEvent p_event) { if (p_event.mouse_button.button_index==BUTTON_LEFT) { gui.drag_accum=Vector2(); gui.drag_attempted=false; - if (gui.drag_data.get_type()!=Variant::NIL) { - _propagate_viewport_notification(this,NOTIFICATION_DRAG_END); - } - gui.drag_data=Variant(); } } + p_event.mouse_button.global_x = pos.x; p_event.mouse_button.global_y = pos.y; @@ -1828,30 +1856,55 @@ void Viewport::_gui_input_event(InputEvent p_event) { get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID); get_tree()->set_input_as_handled(); + + if (gui.drag_data.get_type()!=Variant::NIL && p_event.mouse_button.button_index==BUTTON_LEFT) { + + //alternate drop use (when using force_drag(), as proposed by #5342 + if (gui.mouse_focus && gui.mouse_focus->can_drop_data(pos,gui.drag_data)) { + gui.mouse_focus->drop_data(pos,gui.drag_data); + } + + gui.drag_data=Variant(); + + if (gui.drag_preview) { + memdelete( gui.drag_preview ); + gui.drag_preview=NULL; + } + _propagate_viewport_notification(this,NOTIFICATION_DRAG_END); + //change mouse accordingly + } + + + _gui_cancel_tooltip(); //gui.tooltip_popup->hide(); } else { - if (gui.drag_preview && p_event.mouse_button.button_index==BUTTON_LEFT) { - memdelete( gui.drag_preview ); - gui.drag_preview=NULL; - } - if (!gui.mouse_focus) { - if (gui.mouse_over && gui.drag_data.get_type()!=Variant::NIL && p_event.mouse_button.button_index==BUTTON_LEFT) { + if (gui.drag_data.get_type()!=Variant::NIL && p_event.mouse_button.button_index==BUTTON_LEFT) { + if (gui.mouse_over) { Size2 pos = mpos; pos = gui.focus_inv_xform.xform(pos); if (gui.mouse_over->can_drop_data(pos,gui.drag_data)) { gui.mouse_over->drop_data(pos,gui.drag_data); } - gui.drag_data=Variant(); - _propagate_viewport_notification(this,NOTIFICATION_DRAG_END); - //change mouse accordingly } + if (gui.drag_preview && p_event.mouse_button.button_index==BUTTON_LEFT) { + memdelete( gui.drag_preview ); + gui.drag_preview=NULL; + } + + gui.drag_data=Variant(); + _propagate_viewport_notification(this,NOTIFICATION_DRAG_END); + //change mouse accordingly + } + + if (!gui.mouse_focus) { + //release event is only sent if a mouse focus (previously pressed button) exists break; } @@ -1871,10 +1924,10 @@ void Viewport::_gui_input_event(InputEvent p_event) { gui.mouse_focus_button=-1; } - if (gui.drag_data.get_type()!=Variant::NIL && p_event.mouse_button.button_index==BUTTON_LEFT) { + /*if (gui.drag_data.get_type()!=Variant::NIL && p_event.mouse_button.button_index==BUTTON_LEFT) { _propagate_viewport_notification(this,NOTIFICATION_DRAG_END); gui.drag_data=Variant(); //always clear - } + }*/ get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID); @@ -2032,7 +2085,12 @@ void Viewport::_gui_input_event(InputEvent p_event) { case InputEvent::JOYSTICK_BUTTON: case InputEvent::KEY: { - if (gui.key_focus) { + + if (gui.key_focus && !gui.key_focus->is_visible()) { + gui.key_focus->release_focus(); + } + + if (gui.key_focus) { gui.key_event_accepted=false; if (gui.key_focus->can_process()) { @@ -2172,6 +2230,9 @@ void Viewport::_gui_remove_from_modal_stack(List<Control*>::Element *MI,ObjectID void Viewport::_gui_force_drag(Control *p_base, const Variant& p_data, Control *p_control) { + ERR_EXPLAIN("Drag data must be a value"); + ERR_FAIL_COND(p_data.get_type()==Variant::NIL); + gui.drag_data=p_data; gui.mouse_focus=NULL; @@ -2368,8 +2429,8 @@ void Viewport::input(const InputEvent& p_event) { ERR_FAIL_COND(!is_inside_tree()); + get_tree()->_call_input_pause(input_group,"_input",p_event); //not a bug, must happen before GUI, order is _input -> gui input -> _unhandled input _gui_input_event(p_event); - get_tree()->_call_input_pause(input_group,"_input",p_event); //get_tree()->call_group(SceneTree::GROUP_CALL_REVERSE|SceneTree::GROUP_CALL_REALTIME|SceneTree::GROUP_CALL_MULIILEVEL,gui_input_group,"_gui_input",p_event); //special one for GUI, as controls use their own process check } @@ -2498,6 +2559,9 @@ Variant Viewport::gui_get_drag_data() const { return gui.drag_data; } +Control *Viewport::get_modal_stack_top() const { + return gui.modal_stack.size()?gui.modal_stack.back()->get():NULL; +} String Viewport::get_configuration_warning() const { diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 545020dfc7..22a97a9888 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -39,6 +39,7 @@ */ class Camera; +class Camera2D; class Listener; class Control; class CanvasItem; @@ -374,6 +375,7 @@ public: bool gui_has_modal_stack() const; Variant gui_get_drag_data() const; + Control *get_modal_stack_top() const; virtual String get_configuration_warning() const; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index c83ab88c73..bc0951e436 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -637,10 +637,10 @@ void register_scene_types() { resource_saver_text = memnew( ResourceFormatSaverText ); - ResourceSaver::add_resource_format_saver(resource_saver_text); + ResourceSaver::add_resource_format_saver(resource_saver_text,true); resource_loader_text = memnew( ResourceFormatLoaderText ); - ResourceLoader::add_resource_format_loader(resource_loader_text); + ResourceLoader::add_resource_format_loader(resource_loader_text,true); } diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 098801bcf5..1d15b6f2bc 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -1997,9 +1997,6 @@ void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,fl void Animation::optimize(float p_allowed_linear_err,float p_allowed_angular_err,float p_angle_max) { - - int total_tt=0; - for(int i=0;i<tracks.size();i++) { if (tracks[i]->type==TYPE_TRANSFORM) diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index 88ff09e961..29460790ff 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -644,7 +644,7 @@ Vector2 Curve2D::interpolate_baked(float p_offset,bool p_cubic) const{ if (p_offset>=baked_max_ofs) return r[bpc-1]; - int idx = Math::floor(p_offset/bake_interval); + int idx = Math::floor((double)p_offset/(double)bake_interval); float frac = Math::fmod(p_offset,bake_interval); if (idx>=bpc-1) { @@ -1117,7 +1117,7 @@ Vector3 Curve3D::interpolate_baked(float p_offset,bool p_cubic) const{ if (p_offset>=baked_max_ofs) return r[bpc-1]; - int idx = Math::floor(p_offset/bake_interval); + int idx = Math::floor((double)p_offset/(double)bake_interval); float frac = Math::fmod(p_offset,bake_interval); if (idx>=bpc-1) { @@ -1161,7 +1161,7 @@ float Curve3D::interpolate_baked_tilt(float p_offset) const{ if (p_offset>=baked_max_ofs) return r[bpc-1]; - int idx = Math::floor(p_offset/bake_interval); + int idx = Math::floor((double)p_offset/(double)bake_interval); float frac = Math::fmod(p_offset,bake_interval); if (idx>=bpc-1) { diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 7ed83f50f8..499cf0a169 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -54,8 +54,10 @@ static Ref<StyleBoxTexture> make_stylebox(T p_src,float p_left, float p_top, flo texture = Ref<ImageTexture>( memnew( ImageTexture ) ); Image img(p_src); - if (scale>1) + if (scale>1) { + img.convert(Image::FORMAT_RGBA); img.expand_x2_hq2x(); + } texture->create_from_image( img,ImageTexture::FLAG_FILTER ); (*tex_cache)[p_src]=texture; } @@ -92,8 +94,10 @@ static Ref<Texture> make_icon(T p_src) { Ref<ImageTexture> texture( memnew( ImageTexture ) ); Image img = Image(p_src); - if (scale>1) + if (scale>1) { + img.convert(Image::FORMAT_RGBA); img.expand_x2_hq2x(); + } texture->create_from_image( img,ImageTexture::FLAG_FILTER ); return texture; @@ -473,6 +477,7 @@ void fill_default_theme(Ref<Theme>& t,const Ref<Font> & default_font,const Ref<F t->set_color("completion_selected_color", "TextEdit",Color::html("434244")); t->set_color("completion_existing_color", "TextEdit",Color::html("21dfdfdf")); t->set_color("completion_scroll_color","TextEdit", control_font_color_pressed ); + t->set_color("completion_font_color","TextEdit", Color::html("aaaaaa")); t->set_color("font_color","TextEdit", control_font_color ); t->set_color("font_color_selected","TextEdit", Color(0,0,0) ); t->set_color("selection_color","TextEdit", font_color_selection ); @@ -480,8 +485,14 @@ void fill_default_theme(Ref<Theme>& t,const Ref<Font> & default_font,const Ref<F t->set_color("breakpoint_color","TextEdit", Color(0.8,0.8,0.4,0.2) ); t->set_color("current_line_color","TextEdit", Color(0.25,0.25,0.26,0.8) ); t->set_color("caret_color","TextEdit", control_font_color ); + t->set_color("caret_background_color", "TextEdit", Color::html("000000")); t->set_color("symbol_color","TextEdit", control_font_color_hover ); t->set_color("brace_mismatch_color","TextEdit", Color(1,0.2,0.2) ); + t->set_color("line_number_color","TextEdit",Color::html("66aaaaaa")); + t->set_color("function_color","TextEdit",Color::html("66a2ce")); + t->set_color("member_variable_color","TextEdit",Color::html("e64e59")); + t->set_color("number_color","TextEdit",Color::html("EB9532")); + t->set_color("word_highlighted_color","TextEdit",Color(0.8,0.9,0.9,0.15)); t->set_constant("completion_lines","TextEdit", 7 ); t->set_constant("completion_max_width","TextEdit", 50 ); diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp index c3b40f7add..67587a8f8b 100644 --- a/scene/resources/dynamic_font.cpp +++ b/scene/resources/dynamic_font.cpp @@ -434,7 +434,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) { int w = slot->bitmap.width; int h = slot->bitmap.rows; - int p = slot->bitmap.pitch; + //int p = slot->bitmap.pitch; int yofs=slot->bitmap_top; int xofs=slot->bitmap_left; int advance=slot->advance.x>>6; diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 6ad8a95565..1afa3fec19 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -71,6 +71,11 @@ void Font::draw(RID p_canvas_item, const Point2& p_pos, const String& p_text, co } } +void Font::update_changes() { + + emit_changed(); +} + void Font::_bind_methods() { ObjectTypeDB::bind_method(_MD("draw","canvas_item","pos","string","modulate","clip_w"),&Font::draw,DEFVAL(Color(1,1,1)),DEFVAL(-1)); @@ -80,6 +85,7 @@ void Font::_bind_methods() { ObjectTypeDB::bind_method(_MD("is_distance_field_hint"),&Font::is_distance_field_hint); ObjectTypeDB::bind_method(_MD("get_string_size","string"),&Font::get_string_size); ObjectTypeDB::bind_method(_MD("draw_char","canvas_item","pos","char","next","modulate"),&Font::draw_char,DEFVAL(-1),DEFVAL(Color(1,1,1))); + ObjectTypeDB::bind_method(_MD("update_changes"),&Font::update_changes); } diff --git a/scene/resources/font.h b/scene/resources/font.h index 67836564cd..fe4558f9e3 100644 --- a/scene/resources/font.h +++ b/scene/resources/font.h @@ -61,6 +61,7 @@ public: void draw_halign(RID p_canvas_item, const Point2& p_pos, HAlign p_align,float p_width,const String& p_text,const Color& p_modulate=Color(1,1,1)) const; virtual float draw_char(RID p_canvas_item, const Point2& p_pos, CharType p_char, CharType p_next=0,const Color& p_modulate=Color(1,1,1)) const=0; + void update_changes(); Font(); }; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index e56314c1f8..9dc54ef0e4 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -68,7 +68,7 @@ void Material::set_flag(Flag p_flag,bool p_enabled) { void Material::set_blend_mode(BlendMode p_blend_mode) { - ERR_FAIL_INDEX(p_blend_mode,3); + ERR_FAIL_INDEX(p_blend_mode,4); blend_mode=p_blend_mode; VisualServer::get_singleton()->material_set_blend_mode(material,(VS::MaterialBlendMode)p_blend_mode); _change_notify(); @@ -406,10 +406,10 @@ void FixedMaterial::_bind_methods() { BIND_CONSTANT( PARAM_SHADE_PARAM ); BIND_CONSTANT( PARAM_MAX ); - BIND_CONSTANT( TEXCOORD_SPHERE ); BIND_CONSTANT( TEXCOORD_UV ); BIND_CONSTANT( TEXCOORD_UV_TRANSFORM ); BIND_CONSTANT( TEXCOORD_UV2 ); + BIND_CONSTANT( TEXCOORD_SPHERE ); BIND_CONSTANT( FLAG_USE_ALPHA ); BIND_CONSTANT( FLAG_USE_COLOR_ARRAY ); diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index a1a1f0a935..921466585d 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -30,7 +30,8 @@ #include "scene/resources/concave_polygon_shape.h" #include "scene/resources/convex_polygon_shape.h" #include "surface_tool.h" -static const char*_array_name[]={ + +static const char* _array_name[]={ "vertex_array", "normal_array", "tangent_array", @@ -847,7 +848,6 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { } { - int tc=0; DVector<int>::Write ir; DVector<int> indices =arrays[ARRAY_INDEX]; bool has_indices=false; diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index ac528e6659..f16d68a521 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -375,7 +375,7 @@ Error SceneState::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map<S PackState ps; ps.node=node; ps.state=state; - pack_state_stack.push_front(ps); + pack_state_stack.push_back(ps); instanced_by_owner=false; } } @@ -471,7 +471,6 @@ Error SceneState::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map<S } } #endif - int subscene_prop_search_from=0; // all setup, we then proceed to check all properties for the node // and save the ones that are worth saving @@ -479,8 +478,6 @@ Error SceneState::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map<S List<PropertyInfo> plist; p_node->get_property_list(&plist); - bool saved_script=false; - for (List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) { @@ -528,23 +525,8 @@ Error SceneState::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map<S break; } } -#if 0 -// this workaround ended up causing problems: -https://github.com/godotengine/godot/issues/3127 - if (saved_script && exists && p_node->get_script_instance()) { - //if this is an overriden value by another script, save it anyway - //as the script change will erase it - //https://github.com/godotengine/godot/issues/2958 - - bool valid=false; - p_node->get_script_instance()->get_property_type(name,&valid); - if (valid) { - exists=false; - isdefault=false; - } - } -#endif + if (exists) { //check if already exists and did not change @@ -556,6 +538,7 @@ https://github.com/godotengine/godot/issues/3127 if (Math::abs(a-b)<CMP_EPSILON) continue; } else if (bool(Variant::evaluate(Variant::OP_EQUAL,value,original))) { + continue; } } @@ -575,9 +558,6 @@ https://github.com/godotengine/godot/issues/3127 } } - if (name=="script/script") - saved_script=true; - NodeData::Property prop; prop.name=_nm_get_string( name,name_map); prop.value=_vm_get_variant( value, variant_map); @@ -729,6 +709,7 @@ Error SceneState::_parse_connections(Node *p_owner,Node *p_node, Map<StringName, List<MethodInfo> _signals; p_node->get_signal_list(&_signals); + _signals.sort(); //ERR_FAIL_COND_V( !node_map.has(p_node), ERR_BUG); //NodeData &nd = nodes[node_map[p_node]]; @@ -738,6 +719,9 @@ Error SceneState::_parse_connections(Node *p_owner,Node *p_node, Map<StringName, List<Node::Connection> conns; p_node->get_signal_connection_list(E->get().name,&conns); + + conns.sort(); + for(List<Node::Connection>::Element *F=conns.front();F;F=F->next()) { const Node::Connection &c = F->get(); @@ -748,22 +732,62 @@ Error SceneState::_parse_connections(Node *p_owner,Node *p_node, Map<StringName, // only connections that originate or end into main saved scene are saved // everything else is discarded - Node *n=c.target->cast_to<Node>(); - if (!n) { + + Node *target=c.target->cast_to<Node>(); + + + if (!target) { continue; } - //source node is outside saved scene? - bool src_is_out = p_node!=p_owner && (p_node->get_filename()!=String() || p_node->get_owner()!=p_owner); - //target node is outside saved scene? - bool dst_is_out = n!=p_owner && (n->get_filename()!=String() || n->get_owner()!=p_owner); + //find if this connection already exists + Node *common_parent = target->find_common_parent_with(p_node); + + ERR_CONTINUE(!common_parent); + + if (common_parent!=p_owner && common_parent->get_filename()==String()) { + common_parent=common_parent->get_owner(); + } + + bool exists=false; + + //go through ownership chain to see if this exists + while(common_parent) { + + + + Ref<SceneState> ps; + + if (common_parent==p_owner) + ps=common_parent->get_scene_inherited_state(); + else + ps=common_parent->get_scene_instance_state(); + + + if (ps.is_valid()) { + + NodePath signal_from = common_parent->get_path_to(p_node); + NodePath signal_to = common_parent->get_path_to(target); + + if (ps->has_connection(signal_from,c.signal,signal_to,c.method)) { + exists=true; + break; + } + + } - //if both are out, ignore connection - if (src_is_out && dst_is_out) { + if (common_parent==p_owner) + break; + else + common_parent=common_parent->get_owner(); + } + + if (exists) { //already exists (comes from instance or inheritance), so don't save continue; } + { Node *nl=p_node; @@ -776,7 +800,7 @@ Error SceneState::_parse_connections(Node *p_owner,Node *p_node, Map<StringName, Ref<SceneState> state = nl->get_scene_inherited_state(); if (state.is_valid()) { int from_node = state->find_node_by_path(nl->get_path_to(p_node)); - int to_node = state->find_node_by_path(nl->get_path_to(n)); + int to_node = state->find_node_by_path(nl->get_path_to(target)); if (from_node>=0 && to_node>=0) { //this one has state for this node, save @@ -794,7 +818,7 @@ Error SceneState::_parse_connections(Node *p_owner,Node *p_node, Map<StringName, Ref<SceneState> state = nl->get_scene_instance_state(); if (state.is_valid()) { int from_node = state->find_node_by_path(nl->get_path_to(p_node)); - int to_node = state->find_node_by_path(nl->get_path_to(n)); + int to_node = state->find_node_by_path(nl->get_path_to(target)); if (from_node>=0 && to_node>=0) { //this one has state for this node, save @@ -835,14 +859,14 @@ Error SceneState::_parse_connections(Node *p_owner,Node *p_node, Map<StringName, int target_id; - if (node_map.has(n)) { - target_id=node_map[n]; + if (node_map.has(target)) { + target_id=node_map[target]; } else { - if (nodepath_map.has(n)) { - target_id=FLAG_ID_IS_PATH|nodepath_map[n]; + if (nodepath_map.has(target)) { + target_id=FLAG_ID_IS_PATH|nodepath_map[target]; } else { int sidx=nodepath_map.size(); - nodepath_map[n]=sidx; + nodepath_map[target]=sidx; target_id=FLAG_ID_IS_PATH|sidx; } } @@ -1494,6 +1518,8 @@ StringName SceneState::get_connection_method(int p_idx) const{ return names[connections[p_idx].method]; } + + int SceneState::get_connection_flags(int p_idx) const{ ERR_FAIL_INDEX_V(p_idx,connections.size(),-1); @@ -1510,6 +1536,38 @@ Array SceneState::get_connection_binds(int p_idx) const { return binds; } +bool SceneState::has_connection(const NodePath& p_node_from, const StringName& p_signal, const NodePath& p_node_to, const StringName& p_method) const { + + for(int i=0;i<connections.size();i++) { + const ConnectionData &c = connections[i]; + + NodePath np_from; + + if (c.from&FLAG_ID_IS_PATH) { + np_from=node_paths[c.from&FLAG_MASK]; + } else { + np_from=get_node_path(c.from); + } + + NodePath np_to; + + if (c.to&FLAG_ID_IS_PATH) { + np_to=node_paths[c.to&FLAG_MASK]; + } else { + np_to=get_node_path(c.to); + } + + StringName sn_signal=names[c.signal]; + StringName sn_method=names[c.method]; + + if (np_from==p_node_from && sn_signal==p_signal && np_to==p_node_to && sn_method==p_method) { + return true; + } + } + + return false; +} + Vector<NodePath> SceneState::get_editable_instances() const { return editable_instances; } @@ -1521,6 +1579,16 @@ int SceneState::add_name(const StringName& p_name) { return names.size()-1; } +int SceneState::find_name(const StringName& p_name) const { + + for(int i=0;i<names.size();i++) { + if (names[i]==p_name) + return i; + } + + return -1; +} + int SceneState::add_value(const Variant& p_value) { variants.push_back(p_value); diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h index 6bde508d72..f0e530f88a 100644 --- a/scene/resources/packed_scene.h +++ b/scene/resources/packed_scene.h @@ -163,11 +163,14 @@ public: int get_connection_flags(int p_idx) const; Array get_connection_binds(int p_idx) const; + bool has_connection(const NodePath &p_node_from, const StringName& p_signal, const NodePath &p_node_to, const StringName& p_method) const; + Vector<NodePath> get_editable_instances() const; //build API int add_name(const StringName& p_name); + int find_name(const StringName& p_name) const; int add_value(const Variant& p_value); int add_node_path(const NodePath& p_path); int add_node(int p_parent,int p_owner,int p_type,int p_name, int p_instance); @@ -196,6 +199,7 @@ class PackedScene : public Resource { protected: + virtual bool editor_can_reload_from_file() { return false; } // this is handled by editor better static void _bind_methods(); public: diff --git a/scene/resources/sample.cpp b/scene/resources/sample.cpp index 87fcfc425d..aae4e85a27 100644 --- a/scene/resources/sample.cpp +++ b/scene/resources/sample.cpp @@ -187,6 +187,8 @@ RID Sample::get_rid() const { return sample; } + + void Sample::_bind_methods(){ diff --git a/scene/resources/sample.h b/scene/resources/sample.h index 0a88167233..18672e41c0 100644 --- a/scene/resources/sample.h +++ b/scene/resources/sample.h @@ -75,6 +75,7 @@ protected: public: + void create(Format p_format, bool p_stereo, int p_length); Format get_format() const; diff --git a/scene/resources/sample_library.cpp b/scene/resources/sample_library.cpp index 5b70ee0e11..67481f267d 100644 --- a/scene/resources/sample_library.cpp +++ b/scene/resources/sample_library.cpp @@ -106,9 +106,9 @@ void SampleLibrary::remove_sample(const StringName& p_name) { sample_map.erase(p_name); } -void SampleLibrary::get_sample_list(List<StringName> *p_samples) { +void SampleLibrary::get_sample_list(List<StringName> *p_samples) const { - for(Map<StringName,SampleData >::Element *E=sample_map.front();E;E=E->next()) { + for(const Map<StringName,SampleData >::Element *E=sample_map.front();E;E=E->next()) { p_samples->push_back(E->key()); } @@ -122,9 +122,17 @@ bool SampleLibrary::has_sample(const StringName& p_name) const { void SampleLibrary::_get_property_list(List<PropertyInfo> *p_list) const { + + List<PropertyInfo> tpl; for(Map<StringName,SampleData>::Element *E=sample_map.front();E;E=E->next()) { - p_list->push_back( PropertyInfo( Variant::DICTIONARY, "samples/"+E->key(),PROPERTY_HINT_RESOURCE_TYPE,"Sample",PROPERTY_USAGE_NOEDITOR ) ); + tpl.push_back( PropertyInfo( Variant::DICTIONARY, "samples/"+E->key(),PROPERTY_HINT_RESOURCE_TYPE,"Sample",PROPERTY_USAGE_NOEDITOR ) ); + } + + tpl.sort(); + //sort so order is kept + for(List<PropertyInfo>::Element *E=tpl.front();E;E=E->next()) { + p_list->push_back(E->get()); } } @@ -169,7 +177,20 @@ float SampleLibrary::sample_get_pitch_scale(const StringName& p_name) const{ return sample_map[p_name].pitch_scale; } +Array SampleLibrary::_get_sample_list() const { + List<StringName> snames; + get_sample_list(&snames); + + snames.sort_custom<StringName::AlphCompare>(); + + Array ret; + for (List<StringName>::Element *E=snames.front();E;E=E->next()) { + ret.push_back(E->get()); + } + + return ret; +} void SampleLibrary::_bind_methods() { @@ -178,6 +199,8 @@ void SampleLibrary::_bind_methods() { ObjectTypeDB::bind_method(_MD("has_sample","name"),&SampleLibrary::has_sample ); ObjectTypeDB::bind_method(_MD("remove_sample","name"),&SampleLibrary::remove_sample ); + ObjectTypeDB::bind_method(_MD("get_sample_list"),&SampleLibrary::_get_sample_list ); + ObjectTypeDB::bind_method(_MD("sample_set_volume_db","name","db"),&SampleLibrary::sample_set_volume_db ); ObjectTypeDB::bind_method(_MD("sample_get_volume_db","name"),&SampleLibrary::sample_get_volume_db ); diff --git a/scene/resources/sample_library.h b/scene/resources/sample_library.h index 8377967106..e572aa215a 100644 --- a/scene/resources/sample_library.h +++ b/scene/resources/sample_library.h @@ -47,6 +47,8 @@ class SampleLibrary : public Resource { }; Map<StringName,SampleData > sample_map; + + Array _get_sample_list() const; protected: bool _set(const StringName& p_name, const Variant& p_value); @@ -66,7 +68,7 @@ public: void sample_set_pitch_scale(const StringName& p_name, float p_pitch); float sample_get_pitch_scale(const StringName& p_name) const; Ref<Sample> get_sample(const StringName& p_name) const; - void get_sample_list(List<StringName> *p_samples); + void get_sample_list(List<StringName> *p_samples) const; void remove_sample(const StringName& p_name); StringName get_sample_idx(int p_idx) const; diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp index c7e2fc4e73..7bb9ca90ae 100644 --- a/scene/resources/scene_format_text.cpp +++ b/scene/resources/scene_format_text.cpp @@ -67,12 +67,17 @@ Error ResourceInteractiveLoaderText::_parse_sub_resource(VariantParser::Stream* String path = local_path+"::"+itos(index); - if (!ResourceCache::has(path)) { - r_err_str="Can't load cached sub-resource: "+path; - return ERR_PARSE_ERROR; - } + if (!ignore_resource_parsing) { - r_res=RES(ResourceCache::get(path)); + if (!ResourceCache::has(path)) { + r_err_str="Can't load cached sub-resource: "+path; + return ERR_PARSE_ERROR; + } + + r_res=RES(ResourceCache::get(path)); + } else { + r_res=RES(); + } VariantParser::get_token(p_stream,token,line,r_err_str); if (token.type!=VariantParser::TK_PARENTHESIS_CLOSE) { @@ -95,25 +100,29 @@ Error ResourceInteractiveLoaderText::_parse_ext_resource(VariantParser::Stream* int id = token.value; + if (!ignore_resource_parsing) { - if (!ext_resources.has(id)) { - r_err_str="Can't load cached ext-resource #"+itos(id); - return ERR_PARSE_ERROR; - } + if (!ext_resources.has(id)) { + r_err_str="Can't load cached ext-resource #"+itos(id); + return ERR_PARSE_ERROR; + } - String path = ext_resources[id].path; - String type = ext_resources[id].type; + String path = ext_resources[id].path; + String type = ext_resources[id].type; - if (path.find("://")==-1 && path.is_rel_path()) { - // path is relative to file being loaded, so convert to a resource path - path=Globals::get_singleton()->localize_path(res_path.get_base_dir().plus_file(path)); + if (path.find("://")==-1 && path.is_rel_path()) { + // path is relative to file being loaded, so convert to a resource path + path=Globals::get_singleton()->localize_path(res_path.get_base_dir().plus_file(path)); - } + } - r_res=ResourceLoader::load(path,type); + r_res=ResourceLoader::load(path,type); - if (r_res.is_null()) { - WARN_PRINT(String("Couldn't load external resource: "+path).utf8().get_data()); + if (r_res.is_null()) { + WARN_PRINT(String("Couldn't load external resource: "+path).utf8().get_data()); + } + } else { + r_res=RES(); } VariantParser::get_token(p_stream,token,line,r_err_str); @@ -395,7 +404,9 @@ Error ResourceInteractiveLoaderText::poll() { } if (next_tag.fields.has("parent")) { - parent=packed_scene->get_state()->add_node_path(next_tag.fields["parent"]); + NodePath np = next_tag.fields["parent"]; + np.prepend_period(); //compatible to how it manages paths internally + parent=packed_scene->get_state()->add_node_path(np); } @@ -625,6 +636,7 @@ void ResourceInteractiveLoaderText::get_dependencies(FileAccess *f,List<String> open(f); + ignore_resource_parsing=true; ERR_FAIL_COND(error!=OK); while(next_tag.name=="ext_resource") { @@ -662,6 +674,7 @@ void ResourceInteractiveLoaderText::get_dependencies(FileAccess *f,List<String> Error err = VariantParser::parse_tag(&stream,lines,error_text,next_tag,&rp); if (err) { + print_line(error_text+" - "+itos(lines)); error_text="Unexpected end of file"; _printerr(); error=ERR_FILE_CORRUPT; @@ -676,7 +689,7 @@ Error ResourceInteractiveLoaderText::rename_dependencies(FileAccess *p_f, const open(p_f,true); ERR_FAIL_COND_V(error!=OK,error); - + ignore_resource_parsing=true; //FileAccess FileAccess *fw = NULL; @@ -794,7 +807,7 @@ void ResourceInteractiveLoaderText::open(FileAccess *p_f,bool p_skip_first_tag) stream.f=f; is_scene=false; - + ignore_resource_parsing=false; resource_current=0; @@ -879,6 +892,8 @@ String ResourceInteractiveLoaderText::recognize(FileAccess *p_f) { stream.f=f; + ignore_resource_parsing=true; + VariantParser::Tag tag; Error err = VariantParser::parse_tag(&stream,lines,error_text,tag); @@ -1296,7 +1311,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path,const RES& p_re if ((PE->get().usage&PROPERTY_USAGE_STORE_IF_NONZERO && value.is_zero())||(PE->get().usage&PROPERTY_USAGE_STORE_IF_NONONE && value.is_one()) ) continue; - if (PE->get().type==Variant::OBJECT && value.is_zero() && (!PE->get().usage&PROPERTY_USAGE_STORE_IF_NULL)) + if (PE->get().type==Variant::OBJECT && value.is_zero() && !(PE->get().usage&PROPERTY_USAGE_STORE_IF_NULL)) continue; String vars; diff --git a/scene/resources/scene_format_text.h b/scene/resources/scene_format_text.h index 8dbfbfda48..6122a1f9d8 100644 --- a/scene/resources/scene_format_text.h +++ b/scene/resources/scene_format_text.h @@ -56,7 +56,7 @@ class ResourceInteractiveLoaderText : public ResourceInteractiveLoader { bool is_scene; String res_type; - + bool ignore_resource_parsing; // Map<String,String> remaps; diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index 12382e6678..e1769d099b 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -752,8 +752,6 @@ void SurfaceTool::generate_normals() { if (smooth_groups.has(0)) smooth=smooth_groups[0]; - print_line("SMOOTH BEGIN? "+itos(smooth)); - List< Vertex >::Element *B=vertex_array.front(); for(List< Vertex >::Element *E=B;E;) { @@ -862,6 +860,7 @@ void SurfaceTool::_bind_methods() { ObjectTypeDB::bind_method(_MD("deindex"),&SurfaceTool::deindex); ///ObjectTypeDB::bind_method(_MD("generate_flat_normals"),&SurfaceTool::generate_flat_normals); ObjectTypeDB::bind_method(_MD("generate_normals"),&SurfaceTool::generate_normals); + ObjectTypeDB::bind_method(_MD("add_index", "index"), &SurfaceTool::add_index); ObjectTypeDB::bind_method(_MD("commit:Mesh","existing:Mesh"),&SurfaceTool::commit,DEFVAL(Variant())); ObjectTypeDB::bind_method(_MD("clear"),&SurfaceTool::clear); diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 2fa00c7da7..726b1938c4 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -98,10 +98,6 @@ Texture::Texture() { -bool ImageTexture::can_reload_from_file() { - - return true; -} void ImageTexture::reload_from_file() { diff --git a/scene/resources/texture.h b/scene/resources/texture.h index 103b425cd8..05ea833978 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -103,7 +103,6 @@ private: float lossy_storage_quality; protected: - virtual bool can_reload_from_file(); virtual void reload_from_file(); bool _set(const StringName& p_name, const Variant& p_value); diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp index 92a6f0c0b9..b351167e10 100644 --- a/scene/resources/theme.cpp +++ b/scene/resources/theme.cpp @@ -219,7 +219,22 @@ Ref<Theme> Theme::get_default() { void Theme::set_default_theme_font( const Ref<Font>& p_default_font ) { + if (default_theme_font==p_default_font) + return; + + if (default_theme_font.is_valid()) { + _unref_font(default_theme_font); + } + default_theme_font=p_default_font; + + if (default_theme_font.is_valid()) { + _ref_font(default_theme_font); + } + + _change_notify(); + emit_changed();; + } Ref<Font> Theme::get_default_theme_font() const { diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp index e96cac170b..6b329a1a73 100644 --- a/scene/resources/world_2d.cpp +++ b/scene/resources/world_2d.cpp @@ -235,19 +235,20 @@ struct SpatialIndexer2D { List<VisibilityNotifier2D*> added; List<VisibilityNotifier2D*> removed; - for(int i=begin.x;i<=end.x;i++) { + int visible_cells=(end.x-begin.x)*(end.y-begin.y); - for(int j=begin.y;j<=end.y;j++) { + if (visible_cells>10000) { - CellKey ck; - ck.x=i; - ck.y=j; + //well you zoomed out a lot, it's your problem. To avoid freezing in the for loops below, we'll manually check cell by cell - Map<CellKey,CellData>::Element *F=cells.find(ck); - if (!F) { - continue; - } + for (Map<CellKey,CellData>::Element *F=cells.front();F;F=F->next()) { + + const CellKey &ck=F->key(); + if (ck.x<begin.x || ck.x>end.x) + continue; + if (ck.y<begin.y || ck.y>end.y) + continue; //notifiers in cell for (Map<VisibilityNotifier2D*,CellRef>::Element *G=F->get().notifiers.front();G;G=G->next()) { @@ -262,6 +263,38 @@ struct SpatialIndexer2D { } } } + + } else { + + //check cells in grid fashion + for(int i=begin.x;i<=end.x;i++) { + + for(int j=begin.y;j<=end.y;j++) { + + CellKey ck; + ck.x=i; + ck.y=j; + + Map<CellKey,CellData>::Element *F=cells.find(ck); + if (!F) { + continue; + } + + + //notifiers in cell + for (Map<VisibilityNotifier2D*,CellRef>::Element *G=F->get().notifiers.front();G;G=G->next()) { + + Map<VisibilityNotifier2D*,uint64_t>::Element *H=E->get().notifiers.find(G->key()); + if (!H) { + + H=E->get().notifiers.insert(G->key(),pass); + added.push_back(G->key()); + } else { + H->get()=pass; + } + } + } + } } for (Map<VisibilityNotifier2D*,uint64_t>::Element *F=E->get().notifiers.front();F;F=F->next()) { |