diff options
Diffstat (limited to 'scene')
82 files changed, 3750 insertions, 428 deletions
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index f98a50e3e0..e576aa10e0 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -29,6 +29,8 @@ #include "camera_2d.h" #include "scene/scene_string_names.h" #include "servers/visual_server.h" +#include "core/math/math_funcs.h" +#include <editor/editor_node.h> void Camera2D::_update_scroll() { @@ -114,7 +116,25 @@ Matrix32 Camera2D::get_camera_transform() { camera_pos=new_camera_pos; } - + Point2 screen_offset = (anchor_mode==ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5 * zoom) : Point2()); + Rect2 screen_rect(-screen_offset+camera_pos,screen_size*zoom); + + if (offset!=Vector2()) + screen_rect.pos+=offset; + + if (limit_smoothing_enabled) { + if (screen_rect.pos.x < limit[MARGIN_LEFT]) + camera_pos.x -= screen_rect.pos.x - limit[MARGIN_LEFT]; + + if (screen_rect.pos.x + screen_rect.size.x > limit[MARGIN_RIGHT]) + camera_pos.x -= screen_rect.pos.x + screen_rect.size.x - limit[MARGIN_RIGHT]; + + if (screen_rect.pos.y + screen_rect.size.y > limit[MARGIN_BOTTOM]) + camera_pos.y -= screen_rect.pos.y + screen_rect.size.y - limit[MARGIN_BOTTOM]; + + if (screen_rect.pos.y < limit[MARGIN_TOP]) + camera_pos.y -= screen_rect.pos.y - limit[MARGIN_TOP]; + } if (smoothing_enabled && !get_tree()->is_editor_hint()) { @@ -144,19 +164,19 @@ Matrix32 Camera2D::get_camera_transform() { } Rect2 screen_rect(-screen_offset+ret_camera_pos,screen_size*zoom); + if (screen_rect.pos.x < limit[MARGIN_LEFT]) + screen_rect.pos.x = limit[MARGIN_LEFT]; + if (screen_rect.pos.x + screen_rect.size.x > limit[MARGIN_RIGHT]) screen_rect.pos.x = limit[MARGIN_RIGHT] - screen_rect.size.x; if (screen_rect.pos.y + screen_rect.size.y > limit[MARGIN_BOTTOM]) screen_rect.pos.y = limit[MARGIN_BOTTOM] - screen_rect.size.y; - - if (screen_rect.pos.x < limit[MARGIN_LEFT]) - screen_rect.pos.x=limit[MARGIN_LEFT]; - if (screen_rect.pos.y < limit[MARGIN_TOP]) screen_rect.pos.y =limit[MARGIN_TOP]; - + + if (offset!=Vector2()) { screen_rect.pos+=offset; @@ -382,6 +402,17 @@ int Camera2D::get_limit(Margin p_margin) const{ } +void Camera2D::set_limit_smoothing_enabled(bool enable) { + + limit_smoothing_enabled = enable; + _update_scroll(); +} + +bool Camera2D::is_limit_smoothing_enabled() const{ + + return limit_smoothing_enabled; +} + void Camera2D::set_drag_margin(Margin p_margin,float p_drag_margin) { ERR_FAIL_INDEX(p_margin,4); @@ -536,13 +567,15 @@ void Camera2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("_update_scroll"),&Camera2D::_update_scroll); - ObjectTypeDB::bind_method(_MD("_set_current","current"),&Camera2D::_set_current); ObjectTypeDB::bind_method(_MD("is_current"),&Camera2D::is_current); ObjectTypeDB::bind_method(_MD("set_limit","margin","limit"),&Camera2D::set_limit); ObjectTypeDB::bind_method(_MD("get_limit","margin"),&Camera2D::get_limit); + ObjectTypeDB::bind_method(_MD("set_limit_smoothing_enabled","limit_smoothing_enabled"),&Camera2D::set_limit_smoothing_enabled); + ObjectTypeDB::bind_method(_MD("is_limit_smoothing_enabled"),&Camera2D::is_limit_smoothing_enabled); + ObjectTypeDB::bind_method(_MD("set_v_drag_enabled","enabled"),&Camera2D::set_v_drag_enabled); ObjectTypeDB::bind_method(_MD("is_v_drag_enabled"),&Camera2D::is_v_drag_enabled); @@ -587,6 +620,7 @@ void Camera2D::_bind_methods() { ADD_PROPERTYI( PropertyInfo(Variant::INT,"limit/top"),_SCS("set_limit"),_SCS("get_limit"),MARGIN_TOP); ADD_PROPERTYI( PropertyInfo(Variant::INT,"limit/right"),_SCS("set_limit"),_SCS("get_limit"),MARGIN_RIGHT); ADD_PROPERTYI( PropertyInfo(Variant::INT,"limit/bottom"),_SCS("set_limit"),_SCS("get_limit"),MARGIN_BOTTOM); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"limit/smoothed"),_SCS("set_limit_smoothing_enabled"),_SCS("is_limit_smoothing_enabled") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"drag_margin/h_enabled"),_SCS("set_h_drag_enabled"),_SCS("is_h_drag_enabled") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"drag_margin/v_enabled"),_SCS("set_v_drag_enabled"),_SCS("is_v_drag_enabled") ); @@ -619,6 +653,7 @@ Camera2D::Camera2D() { limit[MARGIN_TOP]=-10000000; limit[MARGIN_RIGHT]=10000000; limit[MARGIN_BOTTOM]=10000000; + drag_margin[MARGIN_LEFT]=0.2; drag_margin[MARGIN_TOP]=0.2; drag_margin[MARGIN_RIGHT]=0.2; @@ -626,6 +661,7 @@ Camera2D::Camera2D() { camera_pos=Vector2(); first=true; smoothing_enabled=false; + limit_smoothing_enabled=false; smoothing=5.0; zoom = Vector2(1, 1); diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h index b3f55d798d..9f3e4254bb 100644 --- a/scene/2d/camera_2d.h +++ b/scene/2d/camera_2d.h @@ -61,6 +61,7 @@ protected: float smoothing; bool smoothing_enabled; int limit[4]; + bool limit_smoothing_enabled; float drag_margin[4]; bool h_drag_enabled; @@ -68,7 +69,6 @@ protected: float h_ofs; float v_ofs; - Point2 camera_screen_center; void _update_scroll(); @@ -95,6 +95,8 @@ public: void set_limit(Margin p_margin,int p_limit); int get_limit(Margin p_margin) const; + void set_limit_smoothing_enabled(bool enable); + bool is_limit_smoothing_enabled() const; void set_h_drag_enabled(bool p_enabled); bool is_h_drag_enabled() const; diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index eb4f457975..ed1d606ba8 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -650,21 +650,22 @@ int CanvasItem::get_light_mask() const{ } -void CanvasItem::item_rect_changed() { +void CanvasItem::item_rect_changed(bool p_size_changed) { - update(); + if (p_size_changed) + update(); emit_signal(SceneStringNames::get_singleton()->item_rect_changed); } -void CanvasItem::draw_line(const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width) { +void CanvasItem::draw_line(const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width,bool p_antialiased) { if (!drawing) { ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL(); } - VisualServer::get_singleton()->canvas_item_add_line(canvas_item,p_from,p_to,p_color,p_width); + VisualServer::get_singleton()->canvas_item_add_line(canvas_item,p_from,p_to,p_color,p_width,p_antialiased); } void CanvasItem::draw_rect(const Rect2& p_rect, const Color& p_color) { @@ -1028,7 +1029,7 @@ void CanvasItem::_bind_methods() { ObjectTypeDB::bind_method(_MD("_is_on_top"),&CanvasItem::_is_on_top); //ObjectTypeDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform); - ObjectTypeDB::bind_method(_MD("draw_line","from","to","color","width"),&CanvasItem::draw_line,DEFVAL(1.0)); + ObjectTypeDB::bind_method(_MD("draw_line","from","to","color","width","antialiased"),&CanvasItem::draw_line,DEFVAL(1.0),DEFVAL(false)); ObjectTypeDB::bind_method(_MD("draw_rect","rect","color"),&CanvasItem::draw_rect); ObjectTypeDB::bind_method(_MD("draw_circle","pos","radius","color"),&CanvasItem::draw_circle); ObjectTypeDB::bind_method(_MD("draw_texture","texture:Texture","pos","modulate"),&CanvasItem::draw_texture,DEFVAL(Color(1,1,1,1))); diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index b894310ce2..7849a66185 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -157,7 +157,7 @@ protected: _FORCE_INLINE_ void _notify_transform() { if (!is_inside_tree()) return; _notify_transform(this); if (!block_transform_notify && notify_local_transform) notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); } - void item_rect_changed(); + void item_rect_changed(bool p_size_changed=true); void _notification(int p_what); static void _bind_methods(); @@ -207,7 +207,7 @@ public: /* DRAWING API */ - void draw_line(const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width=1.0); + void draw_line(const Point2& p_from, const Point2& p_to, const Color& p_color, float p_width=1.0, bool p_antialiased=false); void draw_rect(const Rect2& p_rect, const Color& p_color); void draw_circle(const Point2& p_pos, float p_radius, const Color& p_color); void draw_texture(const Ref<Texture>& p_texture, const Point2& p_pos, const Color &p_modulate=Color(1,1,1,1)); diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index 134e0153b3..df43e8e373 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -295,6 +295,53 @@ void Node2D::set_global_pos(const Point2& p_pos) { } } + +float Node2D::get_global_rot() const { + + return get_global_transform().get_rotation(); +} + +void Node2D::set_global_rot(float p_radians) { + + CanvasItem *pi = get_parent_item(); + if (pi) { + const float parent_global_rot = pi->get_global_transform().get_rotation(); + set_rot(p_radians - parent_global_rot); + } else { + set_rot(p_radians); + } +} + + +float Node2D::get_global_rotd() const { + + return Math::rad2deg(get_global_rot()); +} + +void Node2D::set_global_rotd(float p_degrees) { + + set_global_rot(Math::deg2rad(p_degrees)); +} + + +Size2 Node2D::get_global_scale() const { + + return get_global_transform().get_scale(); +} + +void Node2D::set_global_scale(const Size2& p_scale) { + + CanvasItem *pi = get_parent_item(); + if (pi) { + const Size2 parent_global_scale = pi->get_global_transform().get_scale(); + set_scale(p_scale - parent_global_scale); + } else { + set_scale(p_scale); + } + +} + + void Node2D::set_transform(const Matrix32& p_transform) { _mat=p_transform; @@ -398,6 +445,12 @@ void Node2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_global_pos","pos"),&Node2D::set_global_pos); ObjectTypeDB::bind_method(_MD("get_global_pos"),&Node2D::get_global_pos); + ObjectTypeDB::bind_method(_MD("set_global_rot","radians"),&Node2D::set_global_rot); + ObjectTypeDB::bind_method(_MD("get_global_rot"),&Node2D::get_global_rot); + ObjectTypeDB::bind_method(_MD("set_global_rotd","degrees"),&Node2D::set_global_rotd); + ObjectTypeDB::bind_method(_MD("get_global_rotd"),&Node2D::get_global_rotd); + ObjectTypeDB::bind_method(_MD("set_global_scale","scale"),&Node2D::set_global_scale); + ObjectTypeDB::bind_method(_MD("get_global_scale"),&Node2D::get_global_scale); ObjectTypeDB::bind_method(_MD("set_transform","xform"),&Node2D::set_transform); ObjectTypeDB::bind_method(_MD("set_global_transform","xform"),&Node2D::set_global_transform); diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h index b0c628fd94..aa8d0ef33c 100644 --- a/scene/2d/node_2d.h +++ b/scene/2d/node_2d.h @@ -87,11 +87,17 @@ public: Size2 get_scale() const; Point2 get_global_pos() const; + float get_global_rot() const; + float get_global_rotd() const; + Size2 get_global_scale() const; virtual Rect2 get_item_rect() const; void set_transform(const Matrix32& p_transform); void set_global_transform(const Matrix32& p_transform); void set_global_pos(const Point2& p_pos); + void set_global_rot(float p_radians); + void set_global_rotd(float p_degrees); + void set_global_scale(const Size2& p_scale); void set_z(int p_z); int get_z() const; diff --git a/scene/2d/parallax_layer.cpp b/scene/2d/parallax_layer.cpp index e9378b1d02..05136de5d6 100644 --- a/scene/2d/parallax_layer.cpp +++ b/scene/2d/parallax_layer.cpp @@ -123,26 +123,15 @@ void ParallaxLayer::set_base_offset_and_scale(const Point2& p_offset,float p_sca Point2 new_ofs = ((orig_offset+p_offset)*motion_scale)*p_scale+motion_offset; if (mirroring.x) { - - while( new_ofs.x>=0) { - new_ofs.x -= mirroring.x*p_scale; - } - while(new_ofs.x < -mirroring.x*p_scale) { - new_ofs.x += mirroring.x*p_scale; - } + double den = mirroring.x*p_scale; + new_ofs.x -= den*ceil(new_ofs.x/den); } if (mirroring.y) { - - while( new_ofs.y>=0) { - new_ofs.y -= mirroring.y*p_scale; - } - while(new_ofs.y < -mirroring.y*p_scale) { - new_ofs.y += mirroring.y*p_scale; - } + double den = mirroring.y*p_scale; + new_ofs.y -= den*ceil(new_ofs.y/den); } - set_pos(new_ofs); set_scale(Vector2(1,1)*p_scale); diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 26c4ea385f..0c5c353766 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -436,7 +436,7 @@ bool RigidBody2D::_test_motion(const Vector2& p_motion,float p_margin,const Ref< Physics2DServer::MotionResult *r=NULL; if (p_result.is_valid()) r=p_result->get_result_ptr(); - return Physics2DServer::get_singleton()->body_test_motion(get_rid(),p_motion,p_margin,r); + return Physics2DServer::get_singleton()->body_test_motion(get_rid(),get_global_transform(),p_motion,p_margin,r); } @@ -1057,8 +1057,10 @@ Vector2 KinematicBody2D::get_travel() const { Vector2 KinematicBody2D::move(const Vector2& p_motion) { #if 1 + + Matrix32 gt = get_global_transform(); Physics2DServer::MotionResult result; - colliding = Physics2DServer::get_singleton()->body_test_motion(get_rid(),p_motion,margin,&result); + colliding = Physics2DServer::get_singleton()->body_test_motion(get_rid(),gt,p_motion,margin,&result); collider_metadata=result.collider_metadata; collider_shape=result.collider_shape; @@ -1067,10 +1069,12 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { normal=result.collision_normal; collider=result.collider_id; - Matrix32 gt = get_global_transform(); + gt.elements[2]+=result.motion; set_global_transform(gt); travel=result.motion; + + return result.remainder; #else @@ -1081,7 +1085,6 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { //this took about a week to get right.. //but is it right? who knows at this point.. - colliding=false; ERR_FAIL_COND_V(!is_inside_tree(),Vector2()); Physics2DDirectSpaceState *dss = Physics2DServer::get_singleton()->space_get_direct_state(get_world_2d()->get_space()); @@ -1099,17 +1102,15 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { bool collided=false; uint32_t mask=0; - if (collide_static) + if (true) mask|=Physics2DDirectSpaceState::TYPE_MASK_STATIC_BODY; - if (collide_kinematic) + if (true) mask|=Physics2DDirectSpaceState::TYPE_MASK_KINEMATIC_BODY; - if (collide_rigid) + if (true) mask|=Physics2DDirectSpaceState::TYPE_MASK_RIGID_BODY; - if (collide_character) + if (true) mask|=Physics2DDirectSpaceState::TYPE_MASK_CHARACTER_BODY; -// print_line("motion: "+p_motion+" margin: "+rtos(margin)); - //print_line("margin: "+rtos(margin)); do { @@ -1145,6 +1146,8 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { break; } + + Matrix32 gt = get_global_transform(); gt.elements[2]+=recover_motion; set_global_transform(gt); @@ -1191,6 +1194,8 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { if (safe>=1) { //not collided colliding=false; + + } else { //it collided, let's get the rest info in unsafe advance @@ -1226,16 +1231,94 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { #endif } + + +Vector2 KinematicBody2D::move_and_slide(const Vector2& p_linear_velocity,const Vector2& p_floor_direction,float p_slope_stop_min_velocity,int p_max_bounces) { + + Vector2 motion = (move_and_slide_floor_velocity+p_linear_velocity)*get_fixed_process_delta_time(); + Vector2 lv = p_linear_velocity; + + move_and_slide_on_floor=false; + move_and_slide_on_ceiling=false; + move_and_slide_on_wall=false; + move_and_slide_colliders.clear(); + move_and_slide_floor_velocity=Vector2(); + + while(p_max_bounces) { + + motion=move(motion); + + if (is_colliding()) { + + + if (p_floor_direction==Vector2()) { + //all is a wall + move_and_slide_on_wall=true; + } else { + if ( get_collision_normal().dot(p_floor_direction) > Math::cos(Math::deg2rad(45))) { //floor + + + move_and_slide_on_floor=true; + move_and_slide_floor_velocity=get_collider_velocity(); + + if (get_travel().length()<1 && ABS((lv.x-move_and_slide_floor_velocity.x))<p_slope_stop_min_velocity) { + revert_motion(); + return Vector2(); + } + } else if ( get_collision_normal().dot(p_floor_direction) < Math::cos(Math::deg2rad(45))) { //ceiling + move_and_slide_on_ceiling=true; + } else { + move_and_slide_on_wall=true; + } + + } + + motion=get_collision_normal().slide(motion); + lv=get_collision_normal().slide(lv); + Variant collider = _get_collider(); + if (collider.get_type()!=Variant::NIL) { + move_and_slide_colliders.push_back(collider); + } + + } else { + break; + } + + p_max_bounces--; + if (motion==Vector2()) + break; + } + + return lv; +} + +bool KinematicBody2D::is_move_and_slide_on_floor() const { + + return move_and_slide_on_floor; +} +bool KinematicBody2D::is_move_and_slide_on_wall() const{ + + return move_and_slide_on_wall; +} +bool KinematicBody2D::is_move_and_slide_on_ceiling() const{ + + return move_and_slide_on_ceiling; +} +Array KinematicBody2D::get_move_and_slide_colliders() const{ + + return move_and_slide_colliders; +} + Vector2 KinematicBody2D::move_to(const Vector2& p_position) { return move(p_position-get_global_pos()); } -bool KinematicBody2D::test_move(const Vector2& p_motion) { +bool KinematicBody2D::test_move(const Matrix32& p_from,const Vector2& p_motion) { ERR_FAIL_COND_V(!is_inside_tree(),false); - return Physics2DServer::get_singleton()->body_test_motion(get_rid(),p_motion,margin); + return Physics2DServer::get_singleton()->body_test_motion(get_rid(),p_from,p_motion,margin); } @@ -1300,8 +1383,9 @@ void KinematicBody2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("move","rel_vec"),&KinematicBody2D::move); ObjectTypeDB::bind_method(_MD("move_to","position"),&KinematicBody2D::move_to); + ObjectTypeDB::bind_method(_MD("move_and_slide","linear_velocity","floor_normal","slope_stop_min_velocity","max_bounces"),&KinematicBody2D::move_and_slide,DEFVAL(Vector2(0,0)),DEFVAL(5),DEFVAL(4)); - ObjectTypeDB::bind_method(_MD("test_move","rel_vec"),&KinematicBody2D::test_move); + ObjectTypeDB::bind_method(_MD("test_move","from","rel_vec"),&KinematicBody2D::test_move); ObjectTypeDB::bind_method(_MD("get_travel"),&KinematicBody2D::get_travel); ObjectTypeDB::bind_method(_MD("revert_motion"),&KinematicBody2D::revert_motion); @@ -1313,6 +1397,10 @@ void KinematicBody2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_collider:Object"),&KinematicBody2D::_get_collider); ObjectTypeDB::bind_method(_MD("get_collider_shape"),&KinematicBody2D::get_collider_shape); ObjectTypeDB::bind_method(_MD("get_collider_metadata:Variant"),&KinematicBody2D::get_collider_metadata); + ObjectTypeDB::bind_method(_MD("get_move_and_slide_colliders"),&KinematicBody2D::get_move_and_slide_colliders); + ObjectTypeDB::bind_method(_MD("is_move_and_slide_on_floor"),&KinematicBody2D::is_move_and_slide_on_floor); + ObjectTypeDB::bind_method(_MD("is_move_and_slide_on_ceiling"),&KinematicBody2D::is_move_and_slide_on_ceiling); + ObjectTypeDB::bind_method(_MD("is_move_and_slide_on_wall"),&KinematicBody2D::is_move_and_slide_on_wall); ObjectTypeDB::bind_method(_MD("set_collision_margin","pixels"),&KinematicBody2D::set_collision_margin); ObjectTypeDB::bind_method(_MD("get_collision_margin","pixels"),&KinematicBody2D::get_collision_margin); @@ -1330,6 +1418,11 @@ KinematicBody2D::KinematicBody2D() : PhysicsBody2D(Physics2DServer::BODY_MODE_KI collider_shape=0; margin=0.08; + + move_and_slide_on_floor=false; + move_and_slide_on_ceiling=false; + move_and_slide_on_wall=false; + } KinematicBody2D::~KinematicBody2D() { diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index 5af65bff33..ea29d873bd 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -302,6 +302,12 @@ class KinematicBody2D : public PhysicsBody2D { Variant collider_metadata; Vector2 travel; + Vector2 move_and_slide_floor_velocity; + bool move_and_slide_on_floor; + bool move_and_slide_on_ceiling; + bool move_and_slide_on_wall; + Array move_and_slide_colliders; + Variant _get_collider() const; _FORCE_INLINE_ bool _ignores_mode(Physics2DServer::BodyMode) const; @@ -313,7 +319,7 @@ public: Vector2 move(const Vector2& p_motion); Vector2 move_to(const Vector2& p_position); - bool test_move(const Vector2& p_motion); + bool test_move(const Matrix32 &p_from, const Vector2& p_motion); bool is_colliding() const; Vector2 get_travel() const; @@ -329,6 +335,13 @@ public: void set_collision_margin(float p_margin); float get_collision_margin() const; + Vector2 move_and_slide(const Vector2& p_linear_velocity, const Vector2& p_floor_direction=Vector2(0,0), float p_slope_stop_min_velocity=5, int p_max_bounces=4); + bool is_move_and_slide_on_floor() const; + bool is_move_and_slide_on_wall() const; + bool is_move_and_slide_on_ceiling() const; + Array get_move_and_slide_colliders() const; + + KinematicBody2D(); ~KinematicBody2D(); diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp index 6cda52fa4e..b5d62adfb4 100644 --- a/scene/2d/ray_cast_2d.cpp +++ b/scene/2d/ray_cast_2d.cpp @@ -29,6 +29,7 @@ #include "ray_cast_2d.h" #include "servers/physics_2d_server.h" #include "collision_object_2d.h" +#include "physics_body_2d.h" void RayCast2D::set_cast_to(const Vector2& p_point) { @@ -106,6 +107,30 @@ bool RayCast2D::is_enabled() const { return enabled; } +void RayCast2D::set_exclude_parent_body(bool p_exclude_parent_body) { + + if (exclude_parent_body==p_exclude_parent_body) + return; + + exclude_parent_body=p_exclude_parent_body; + + if (!is_inside_tree()) + return; + + + + if (get_parent()->cast_to<PhysicsBody2D>()) { + if (exclude_parent_body) + exclude.insert( get_parent()->cast_to<PhysicsBody2D>()->get_rid() ); + else + exclude.erase( get_parent()->cast_to<PhysicsBody2D>()->get_rid() ); + } +} + +bool RayCast2D::get_exclude_parent_body() const{ + + return exclude_parent_body; +} void RayCast2D::_notification(int p_what) { @@ -118,6 +143,12 @@ void RayCast2D::_notification(int p_what) { else set_fixed_process(false); + if (get_parent()->cast_to<PhysicsBody2D>()) { + if (exclude_parent_body) + exclude.insert( get_parent()->cast_to<PhysicsBody2D>()->get_rid() ); + else + exclude.erase( get_parent()->cast_to<PhysicsBody2D>()->get_rid() ); + } } break; case NOTIFICATION_EXIT_TREE: { @@ -254,7 +285,11 @@ void RayCast2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_type_mask","mask"),&RayCast2D::set_type_mask); ObjectTypeDB::bind_method(_MD("get_type_mask"),&RayCast2D::get_type_mask); + ObjectTypeDB::bind_method(_MD("set_exclude_parent_body","mask"),&RayCast2D::set_exclude_parent_body); + ObjectTypeDB::bind_method(_MD("get_exclude_parent_body"),&RayCast2D::get_exclude_parent_body); + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled")); + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"exclude_parent"),_SCS("set_exclude_parent_body"),_SCS("get_exclude_parent_body")); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"cast_to"),_SCS("set_cast_to"),_SCS("get_cast_to")); ADD_PROPERTY(PropertyInfo(Variant::INT,"layer_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_layer_mask"),_SCS("get_layer_mask")); ADD_PROPERTY(PropertyInfo(Variant::INT,"type_mask",PROPERTY_HINT_FLAGS,"Static,Kinematic,Rigid,Character,Area"),_SCS("set_type_mask"),_SCS("get_type_mask")); @@ -269,4 +304,5 @@ RayCast2D::RayCast2D() { layer_mask=1; type_mask=Physics2DDirectSpaceState::TYPE_MASK_COLLISION; cast_to=Vector2(0,50); + exclude_parent_body=true; } diff --git a/scene/2d/ray_cast_2d.h b/scene/2d/ray_cast_2d.h index 54ec42c53e..e1caa8b63e 100644 --- a/scene/2d/ray_cast_2d.h +++ b/scene/2d/ray_cast_2d.h @@ -45,6 +45,7 @@ class RayCast2D : public Node2D { Set<RID> exclude; uint32_t layer_mask; uint32_t type_mask; + bool exclude_parent_body; Vector2 cast_to; @@ -66,6 +67,9 @@ public: void set_type_mask(uint32_t p_mask); uint32_t get_type_mask() const; + void set_exclude_parent_body(bool p_exclude_parent_body); + bool get_exclude_parent_body() const; + bool is_colliding() const; Object *get_collider() const; int get_collider_shape() const; diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp index 5411950976..852bc187d2 100644 --- a/scene/2d/visibility_notifier_2d.cpp +++ b/scene/2d/visibility_notifier_2d.cpp @@ -40,6 +40,9 @@ void VisibilityNotifier2D::_enter_viewport(Viewport* p_viewport) { ERR_FAIL_COND(viewports.has(p_viewport)); viewports.insert(p_viewport); + if (is_inside_tree() && get_tree()->is_editor_hint()) + return; + if (viewports.size()==1) { emit_signal(SceneStringNames::get_singleton()->enter_screen); @@ -54,6 +57,9 @@ void VisibilityNotifier2D::_exit_viewport(Viewport* p_viewport){ ERR_FAIL_COND(!viewports.has(p_viewport)); viewports.erase(p_viewport); + if (is_inside_tree() && get_tree()->is_editor_hint()) + return; + emit_signal(SceneStringNames::get_singleton()->exit_viewport,p_viewport); if (viewports.size()==0) { emit_signal(SceneStringNames::get_singleton()->exit_screen); diff --git a/scene/3d/baked_light_instance.cpp b/scene/3d/baked_light_instance.cpp index fafa62866f..ca3a309568 100644 --- a/scene/3d/baked_light_instance.cpp +++ b/scene/3d/baked_light_instance.cpp @@ -60,6 +60,8 @@ void BakedLightInstance::set_baked_light(const Ref<BakedLight>& p_baked_light) { // VS::get_singleton()->instance_geometry_set_baked_light(E->get()->get_instance(),baked_light.is_valid()?get_instance():RID()); // } } + + update_configuration_warning(); } Ref<BakedLight> BakedLightInstance::get_baked_light() const{ @@ -77,6 +79,14 @@ DVector<Face3> BakedLightInstance::get_faces(uint32_t p_usage_flags) const { } +String BakedLightInstance::get_configuration_warning() const { + if (get_baked_light().is_null()) { + return TTR("BakedLightInstance does not contain a BakedLight resource."); + } + return String(); +} + + void BakedLightInstance::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_baked_light","baked_light"),&BakedLightInstance::set_baked_light); diff --git a/scene/3d/baked_light_instance.h b/scene/3d/baked_light_instance.h index 92c2d50986..002e55df1d 100644 --- a/scene/3d/baked_light_instance.h +++ b/scene/3d/baked_light_instance.h @@ -55,6 +55,8 @@ public: virtual AABB get_aabb() const; virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const; + String get_configuration_warning() const; + BakedLightInstance(); }; diff --git a/scene/3d/immediate_geometry.cpp b/scene/3d/immediate_geometry.cpp index 4964582be4..c9319904bd 100644 --- a/scene/3d/immediate_geometry.cpp +++ b/scene/3d/immediate_geometry.cpp @@ -102,7 +102,7 @@ DVector<Face3> ImmediateGeometry::get_faces(uint32_t p_usage_flags) const { -void ImmediateGeometry::add_sphere(int p_lats,int p_lons,float p_radius) { +void ImmediateGeometry::add_sphere(int p_lats, int p_lons, float p_radius, bool p_add_uv) { for(int i = 1; i <= p_lats; i++) { double lat0 = Math_PI * (-0.5 + (double) (i - 1) / p_lats); @@ -132,6 +132,10 @@ void ImmediateGeometry::add_sphere(int p_lats,int p_lons,float p_radius) { }; #define ADD_POINT(m_idx)\ + if (p_add_uv) {\ + set_uv(Vector2(Math::atan2(v[m_idx].x,v[m_idx].z)/Math_PI * 0.5+0.5,v[m_idx].y*0.5+0.5));\ + set_tangent(Plane(Vector3(-v[m_idx].z,v[m_idx].y,v[m_idx].x),1)); \ + }\ set_normal(v[m_idx]);\ add_vertex(v[m_idx]*p_radius); @@ -149,14 +153,14 @@ 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); ObjectTypeDB::bind_method(_MD("set_uv","uv"),&ImmediateGeometry::set_uv); ObjectTypeDB::bind_method(_MD("set_uv2","uv"),&ImmediateGeometry::set_uv2); ObjectTypeDB::bind_method(_MD("add_vertex","pos"),&ImmediateGeometry::add_vertex); - ObjectTypeDB::bind_method(_MD("add_sphere","lats","lons","radius"),&ImmediateGeometry::add_sphere); + ObjectTypeDB::bind_method(_MD("add_sphere","lats","lons","radius","add_uv"),&ImmediateGeometry::add_sphere,DEFVAL(true)); ObjectTypeDB::bind_method(_MD("end"),&ImmediateGeometry::end); ObjectTypeDB::bind_method(_MD("clear"),&ImmediateGeometry::clear); diff --git a/scene/3d/immediate_geometry.h b/scene/3d/immediate_geometry.h index 28b5735ca8..fc7f4de634 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); @@ -60,7 +62,7 @@ public: void clear(); - void add_sphere(int p_lats,int p_lons,float p_radius); + void add_sphere(int p_lats,int p_lons,float p_radius,bool p_add_uv=true); diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index 6f6f5d3aff..adc8f9c8cf 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -619,6 +619,8 @@ void Tween::_tween_process(float p_delta) { }; object->call(data.key, (const Variant **) arg, data.args, error); } + if (!repeat) + call_deferred("remove", object, data.key); } continue; } diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index 699062fee4..6479dd2d02 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -55,6 +55,8 @@ void BaseButton::_input_event(InputEvent p_event) { if (b.pressed) { + emit_signal("button_down"); + if (!toggle_mode) { //mouse press attempt status.press_attempt=true; @@ -86,6 +88,8 @@ void BaseButton::_input_event(InputEvent p_event) { } else { + emit_signal("button_up"); + if (status.press_attempt && status.pressing_inside) { // released(); emit_signal("released"); @@ -100,9 +104,11 @@ void BaseButton::_input_event(InputEvent p_event) { status.press_attempt=true; status.pressing_inside=true; + emit_signal("button_down"); } else { + emit_signal("button_up"); if (status.press_attempt &&status.pressing_inside) { @@ -173,6 +179,7 @@ void BaseButton::_input_event(InputEvent p_event) { status.pressing_button++; status.press_attempt=true; status.pressing_inside=true; + emit_signal("button_down"); } else if (status.press_attempt) { @@ -185,6 +192,8 @@ void BaseButton::_input_event(InputEvent p_event) { status.press_attempt=false; status.pressing_inside=false; + emit_signal("button_up"); + if (!toggle_mode) { //mouse press attempt pressed(); @@ -416,7 +425,7 @@ Ref<ShortCut> BaseButton:: get_shortcut() const { void BaseButton::_unhandled_input(InputEvent p_event) { - if (!is_disabled() && is_visible() && p_event.is_pressed() && 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 @@ -467,6 +476,8 @@ void BaseButton::_bind_methods() { ADD_SIGNAL( MethodInfo("pressed" ) ); ADD_SIGNAL( MethodInfo("released" ) ); + ADD_SIGNAL( MethodInfo("button_up") ); + ADD_SIGNAL( MethodInfo("button_down") ); ADD_SIGNAL( MethodInfo("toggled", PropertyInfo( Variant::BOOL,"pressed") ) ); ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "disabled"), _SCS("set_disabled"), _SCS("is_disabled")); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "toggle_mode"), _SCS("set_toggle_mode"), _SCS("is_toggle_mode")); diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 06f8c27957..5e66544153 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -41,13 +41,13 @@ void update_material(Ref<CanvasItemMaterial>mat,const Color& p_color,float h,flo if (!sdr.is_valid()) return; - mat->set_shader_param("R",p_color.r); - mat->set_shader_param("G",p_color.g); - mat->set_shader_param("B",p_color.b); - mat->set_shader_param("H",h); - mat->set_shader_param("S",s); - mat->set_shader_param("V",v); - mat->set_shader_param("A",p_color.a); + mat->set_shader_param("R",p_color.r); + mat->set_shader_param("G",p_color.g); + mat->set_shader_param("B",p_color.b); + mat->set_shader_param("H",h); + mat->set_shader_param("S",s); + mat->set_shader_param("V",v); + mat->set_shader_param("A",p_color.a); } void ColorPicker::_notification(int p_what) { @@ -140,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); @@ -174,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; @@ -262,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); } @@ -271,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; @@ -390,9 +397,10 @@ void ColorPicker::_screen_input(const InputEvent &ev) if (!r->get_rect().has_point(Point2(mev.global_x,mev.global_y))) return; Image img =r->get_screen_capture(); - if (!img.empty()) + if (!img.empty()) { last_capture=img; r->queue_screen_capture(); + } if (!last_capture.empty()) set_color(last_capture.get_pixel(mev.global_x,mev.global_y)); } @@ -408,11 +416,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(); } diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index b9ef1f1e2f..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); diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp index 920c6bf1e6..feaf516f42 100644 --- a/scene/gui/container.cpp +++ b/scene/gui/container.cpp @@ -41,6 +41,8 @@ void Container::_child_minsize_changed() { void Container::add_child_notify(Node *p_child) { + Control::add_child_notify(p_child); + Control *control = p_child->cast_to<Control>(); if (!control) return; @@ -50,18 +52,24 @@ void Container::add_child_notify(Node *p_child) { control->connect("visibility_changed",this,"_child_minsize_changed"); queue_sort(); + } void Container::move_child_notify(Node *p_child) { + Control::move_child_notify(p_child); + if (!p_child->cast_to<Control>()) return; queue_sort(); + + } void Container::remove_child_notify(Node *p_child) { + Control::remove_child_notify(p_child); Control *control = p_child->cast_to<Control>(); if (!control) diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index fc27c0d24f..bf35fd25bd 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -422,7 +422,40 @@ void Control::_resize(const Size2& p_size) { _size_changed(); } +//moved theme configuration here, so controls can set up even if still not inside active scene +void Control::add_child_notify(Node *p_child) { + + Control *child_c=p_child->cast_to<Control>(); + if (!child_c) + return; + + if (child_c->data.theme.is_null() && data.theme_owner) { + child_c->data.theme_owner=data.theme_owner; + child_c->notification(NOTIFICATION_THEME_CHANGED); + } +} + +void Control::remove_child_notify(Node *p_child) { + + Control *child_c=p_child->cast_to<Control>(); + if (!child_c) + return; + + if (child_c->data.theme_owner && child_c->data.theme.is_null()) { + child_c->data.theme_owner=NULL; + //notification(NOTIFICATION_THEME_CHANGED); + } + +} + +void Control::_update_canvas_item_transform() { + + Matrix32 xform=Matrix32(data.rotation,get_pos()); + xform.scale_basis(data.scale); + VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(),xform); + +} void Control::_notification(int p_notification) { @@ -512,10 +545,10 @@ void Control::_notification(int p_notification) { } - if (data.theme.is_null() && data.parent && data.parent->data.theme_owner) { - data.theme_owner=data.parent->data.theme_owner; - notification(NOTIFICATION_THEME_CHANGED); - } + //if (data.theme.is_null() && data.parent && data.parent->data.theme_owner) { + // data.theme_owner=data.parent->data.theme_owner; + // notification(NOTIFICATION_THEME_CHANGED); + //} } break; case NOTIFICATION_EXIT_CANVAS: { @@ -547,10 +580,10 @@ void Control::_notification(int p_notification) { data.parent=NULL; data.parent_canvas_item=NULL; - if (data.theme_owner && data.theme.is_null()) { - data.theme_owner=NULL; + //if (data.theme_owner && data.theme.is_null()) { + // data.theme_owner=NULL; //notification(NOTIFICATION_THEME_CHANGED); - } + //} } break; case NOTIFICATION_MOVED_IN_PARENT: { @@ -574,10 +607,9 @@ void Control::_notification(int p_notification) { } break; case NOTIFICATION_DRAW: { - Matrix32 xform=Matrix32(data.rotation,get_pos()); - xform.scale_basis(data.scale); - VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(),xform); - VisualServer::get_singleton()->canvas_item_set_custom_rect( get_canvas_item(),true, Rect2(Point2(),get_size())); + _update_canvas_item_transform(); + VisualServer::get_singleton()->canvas_item_set_custom_rect( get_canvas_item(),!data.disable_visibility_clip, Rect2(Point2(),get_size())); + //emit_signal(SceneStringNames::get_singleton()->draw); } break; @@ -1246,17 +1278,24 @@ void Control::_size_changed() { new_size_cache.x = MAX( minimum_size.x, new_size_cache.x ); new_size_cache.y = MAX( minimum_size.y, new_size_cache.y ); - - if (new_pos_cache == data.pos_cache && new_size_cache == data.size_cache) - return; // did not change, don't emit signal + bool pos_changed = new_pos_cache != data.pos_cache; + bool size_changed = new_size_cache != data.size_cache; data.pos_cache=new_pos_cache; data.size_cache=new_size_cache; - notification(NOTIFICATION_RESIZED); - item_rect_changed(); - _change_notify_margins(); - _notify_transform(); + if (size_changed) { + notification(NOTIFICATION_RESIZED); + } + if (pos_changed || size_changed) { + item_rect_changed(size_changed); + _change_notify_margins(); + _notify_transform(); + } + + if (pos_changed && !size_changed) { + _update_canvas_item_transform(); //move because it won't be updated + } } float Control::_get_parent_range(int p_idx) const { @@ -1865,7 +1904,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>(); @@ -1884,15 +1923,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()) { @@ -1909,6 +1963,9 @@ void Control::set_theme(const Ref<Theme>& p_theme) { } + if (data.theme.is_valid()) { + data.theme->connect("changed",this,"_theme_changed"); + } } @@ -2170,7 +2227,7 @@ void Control::grab_click_focus() { void Control::minimum_size_changed() { - if (!is_inside_tree()) + if (!is_inside_tree() || data.block_minimum_size_adjust) return; if (data.pending_min_size_update) @@ -2244,6 +2301,7 @@ void Control::set_rotation(float p_radians) { data.rotation=p_radians; update(); _notify_transform(); + _change_notify("rect/rotation"); } float Control::get_rotation() const{ @@ -2329,7 +2387,26 @@ Control *Control::get_root_parent_control() const { return const_cast<Control*>(root); } +void Control::set_block_minimum_size_adjust(bool p_block) { + data.block_minimum_size_adjust=p_block; +} +bool Control::is_minimum_size_adjust_blocked() const { + + return data.block_minimum_size_adjust; +} + + +void Control::set_disable_visibility_clip(bool p_ignore) { + + data.disable_visibility_clip=p_ignore; + update(); +} + +bool Control::is_visibility_clip_disabled() const { + + return data.disable_visibility_clip; +} void Control::_bind_methods() { @@ -2448,6 +2525,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"))); @@ -2554,6 +2635,8 @@ Control::Control() { data.scale=Vector2(1,1); data.drag_owner=0; data.modal_frame=0; + data.block_minimum_size_adjust=false; + data.disable_visibility_clip=false; for (int i=0;i<4;i++) { diff --git a/scene/gui/control.h b/scene/gui/control.h index 830ebd1620..558439efbf 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -128,6 +128,9 @@ private: bool ignore_mouse; bool stop_mouse; + bool block_minimum_size_adjust; + bool disable_visibility_clip; + Control *parent; ObjectID drag_owner; bool modal; @@ -172,7 +175,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(); @@ -191,6 +196,8 @@ private: void _unref_font( Ref<Font> p_sc); void _font_changed(); + void _update_canvas_item_transform(); + friend class Viewport; void _modal_stack_remove(); @@ -198,6 +205,9 @@ friend class Viewport; protected: + virtual void add_child_notify(Node *p_child); + virtual void remove_child_notify(Node *p_child); + //virtual void _window_input_event(InputEvent p_event); bool _set(const StringName& p_name, const Variant& p_value); @@ -390,6 +400,13 @@ public: Control *get_root_parent_control() const; + + void set_block_minimum_size_adjust(bool p_block); + bool is_minimum_size_adjust_blocked() const; + + void set_disable_visibility_clip(bool p_ignore); + bool is_visibility_clip_disabled() const; + Control(); ~Control(); diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index 4dbc106834..93e46da82b 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -399,8 +399,6 @@ AcceptDialog::AcceptDialog() { add_child(label); hbc = memnew( HBoxContainer ); - hbc->set_area_as_parent_rect(margin); - hbc->set_anchor_and_margin(MARGIN_TOP,ANCHOR_END,button_margin); add_child(hbc); hbc->add_spacer(); diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index d335399caa..6b43425edc 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -475,7 +475,7 @@ void FileDialog::update_filters() { String flt=filters[i].get_slice(";",0).strip_edges(); String desc=filters[i].get_slice(";",1).strip_edges(); if (desc.length()) - filter->add_item(desc+" ( "+flt+" )"); + filter->add_item(String(XL_MESSAGE(desc))+" ( "+flt+" )"); else filter->add_item("( "+flt+" )"); } @@ -498,6 +498,16 @@ void FileDialog::add_filter(const String& p_filter) { } +void FileDialog::set_filters(const Vector<String>& p_filters){ + filters=p_filters; + update_filters(); + invalidate(); +} + +Vector<String> FileDialog::get_filters() const{ + return filters; +} + String FileDialog::get_current_dir() const { return dir->get_text(); @@ -686,6 +696,8 @@ void FileDialog::_bind_methods() { ObjectTypeDB::bind_method(_MD("clear_filters"),&FileDialog::clear_filters); ObjectTypeDB::bind_method(_MD("add_filter","filter"),&FileDialog::add_filter); + ObjectTypeDB::bind_method(_MD("set_filters","filters"),&FileDialog::set_filters); + ObjectTypeDB::bind_method(_MD("get_filters"),&FileDialog::get_filters); ObjectTypeDB::bind_method(_MD("get_current_dir"),&FileDialog::get_current_dir); ObjectTypeDB::bind_method(_MD("get_current_file"),&FileDialog::get_current_file); ObjectTypeDB::bind_method(_MD("get_current_path"),&FileDialog::get_current_path); @@ -722,6 +734,11 @@ void FileDialog::_bind_methods() { BIND_CONSTANT( ACCESS_USERDATA ); BIND_CONSTANT( ACCESS_FILESYSTEM ); + ADD_PROPERTY( PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Open one,Open many,Open folder,Open any,Save"),_SCS("set_mode"),_SCS("get_mode") ); + ADD_PROPERTY( PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User data,File system"),_SCS("set_access"),_SCS("get_access") ); + ADD_PROPERTY( PropertyInfo(Variant::STRING_ARRAY, "filters"),_SCS("set_filters"),_SCS("get_filters") ); + ADD_PROPERTY( PropertyInfo(Variant::BOOL, "show_hidden_files"),_SCS("set_show_hidden_files"),_SCS("is_showing_hidden_files") ); + } diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h index 1fcf8387ce..150b24cb3f 100644 --- a/scene/gui/file_dialog.h +++ b/scene/gui/file_dialog.h @@ -131,6 +131,8 @@ public: void clear_filters(); void add_filter(const String& p_filter); + void set_filters(const Vector<String>& p_filters); + Vector<String> get_filters() const; void set_enable_multiple_selection(bool p_enable); Vector<String> get_selected_files() const; diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 06b1c42690..0de6add8cb 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -61,6 +61,8 @@ Error GraphEdit::connect_node(const StringName& p_from, int p_from_port,const St c.to_port=p_to_port; connections.push_back(c); top_layer->update(); + update(); + connections_layer->update(); return OK; } @@ -85,6 +87,8 @@ void GraphEdit::disconnect_node(const StringName& p_from, int p_from_port,const connections.erase(E); top_layer->update(); + update(); + connections_layer->update(); return; } } @@ -100,6 +104,15 @@ void GraphEdit::get_connection_list(List<Connection> *r_connections) const { *r_connections=connections; } +void GraphEdit::set_scroll_ofs(const Vector2& p_ofs) { + + setting_scroll_ofs=true; + h_scroll->set_val(p_ofs.x); + v_scroll->set_val(p_ofs.y); + _update_scroll(); + setting_scroll_ofs=false; +} + Vector2 GraphEdit::get_scroll_ofs() const{ return Vector2(h_scroll->get_val(),v_scroll->get_val()); @@ -107,12 +120,23 @@ Vector2 GraphEdit::get_scroll_ofs() const{ void GraphEdit::_scroll_moved(double) { - _update_scroll_offset(); + + if (!awaiting_scroll_offset_update) { + call_deferred("_update_scroll_offset"); + awaiting_scroll_offset_update=true; + } top_layer->update(); + update(); + + if (!setting_scroll_ofs) {//in godot, signals on change value are avoided as a convention + emit_signal("scroll_offset_changed",get_scroll_ofs()); + } } void GraphEdit::_update_scroll_offset() { + set_block_minimum_size_adjust(true); + for(int i=0;i<get_child_count();i++) { GraphNode *gn=get_child(i)->cast_to<GraphNode>(); @@ -122,9 +146,15 @@ void GraphEdit::_update_scroll_offset() { Point2 pos=gn->get_offset()*zoom; pos-=Point2(h_scroll->get_val(),v_scroll->get_val()); gn->set_pos(pos); - gn->set_scale(Vector2(zoom,zoom)); + if (gn->get_scale()!=Vector2(zoom,zoom)) { + gn->set_scale(Vector2(zoom,zoom)); + } } + connections_layer->set_pos(-Point2(h_scroll->get_val(),v_scroll->get_val())*zoom); + set_block_minimum_size_adjust(false); + awaiting_scroll_offset_update=false; + } void GraphEdit::_update_scroll() { @@ -133,6 +163,9 @@ void GraphEdit::_update_scroll() { return; updating=true; + + set_block_minimum_size_adjust(true); + Rect2 screen; for(int i=0;i<get_child_count();i++) { @@ -167,7 +200,13 @@ void GraphEdit::_update_scroll() { else v_scroll->show(); - _update_scroll_offset(); + set_block_minimum_size_adjust(false); + + if (!awaiting_scroll_offset_update) { + call_deferred("_update_scroll_offset"); + awaiting_scroll_offset_update=true; + } + updating=false; } @@ -177,7 +216,21 @@ void GraphEdit::_graph_node_raised(Node* p_gn) { GraphNode *gn=p_gn->cast_to<GraphNode>(); ERR_FAIL_COND(!gn); gn->raise(); + if (gn->is_comment()) { + move_child(gn,0); + } + int first_not_comment=0; + for(int i=0;i<get_child_count();i++) { + GraphNode *gn=get_child(i)->cast_to<GraphNode>(); + if (gn && !gn->is_comment()) { + first_not_comment=i; + break; + } + } + + move_child(connections_layer,first_not_comment); top_layer->raise(); + emit_signal("node_selected",p_gn); } @@ -187,10 +240,14 @@ void GraphEdit::_graph_node_moved(Node *p_gn) { GraphNode *gn=p_gn->cast_to<GraphNode>(); ERR_FAIL_COND(!gn); top_layer->update(); + update(); + connections_layer->update(); } void GraphEdit::add_child_notify(Node *p_child) { + Control::add_child_notify(p_child); + top_layer->call_deferred("raise"); //top layer always on top! GraphNode *gn = p_child->cast_to<GraphNode>(); if (gn) { @@ -200,10 +257,14 @@ void GraphEdit::add_child_notify(Node *p_child) { _graph_node_moved(gn); gn->set_stop_mouse(false); } + + } void GraphEdit::remove_child_notify(Node *p_child) { + Control::remove_child_notify(p_child); + top_layer->call_deferred("raise"); //top layer always on top! GraphNode *gn = p_child->cast_to<GraphNode>(); if (gn) { @@ -228,18 +289,70 @@ void GraphEdit::_notification(int p_what) { h_scroll->set_anchor_and_margin(MARGIN_TOP,ANCHOR_END,hmin.height); h_scroll->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,0); + + zoom_minus->set_icon(get_icon("minus")); + zoom_reset->set_icon(get_icon("reset")); + zoom_plus->set_icon(get_icon("more")); + snap_button->set_icon(get_icon("snap")); // zoom_icon->set_texture( get_icon("Zoom", "EditorIcons")); } if (p_what==NOTIFICATION_DRAW) { + + draw_style_box( get_stylebox("bg"),Rect2(Point2(),get_size()) ); VS::get_singleton()->canvas_item_set_clip(get_canvas_item(),true); + if (is_using_snap()) { + //draw grid + + int snap = get_snap(); + + Vector2 offset = get_scroll_ofs()/zoom; + Size2 size = get_size()/zoom; + + Point2i from = (offset/float(snap)).floor(); + Point2i len = (size/float(snap)).floor()+Vector2(1,1); + + Color grid_minor = get_color("grid_minor"); + Color grid_major = get_color("grid_major"); + + for(int i=from.x;i<from.x+len.x;i++) { + + Color color; + + if (ABS(i)%10==0) + color=grid_major; + else + color=grid_minor; + + float base_ofs = i*snap*zoom - offset.x*zoom; + draw_line(Vector2(base_ofs,0),Vector2(base_ofs,get_size().height),color); + } + + for(int i=from.y;i<from.y+len.y;i++) { + + Color color; + + if (ABS(i)%10==0) + color=grid_major; + else + color=grid_minor; + + float base_ofs = i*snap*zoom - offset.y*zoom; + draw_line(Vector2(0,base_ofs),Vector2(get_size().width,base_ofs),color); + } + + } + + + } if (p_what==NOTIFICATION_RESIZED) { _update_scroll(); top_layer->update(); + } } @@ -247,7 +360,8 @@ bool GraphEdit::_filter_input(const Point2& p_point) { Ref<Texture> port =get_icon("port","GraphNode"); - float grab_r=port->get_width()*0.5; + float grab_r_extend = 2.0; + float grab_r=port->get_width()*0.5*grab_r_extend; for(int i=get_child_count()-1;i>=0;i--) { GraphNode *gn=get_child(i)->cast_to<GraphNode>(); @@ -266,8 +380,9 @@ bool GraphEdit::_filter_input(const Point2& p_point) { for(int j=0;j<gn->get_connection_input_count();j++) { Vector2 pos = gn->get_connection_input_pos(j)+gn->get_pos(); - if (pos.distance_to(p_point)<grab_r) + if (pos.distance_to(p_point)<grab_r) { return true; + } } @@ -279,11 +394,13 @@ bool GraphEdit::_filter_input(const Point2& p_point) { void GraphEdit::_top_layer_input(const InputEvent& p_ev) { + + float grab_r_extend = 2.0; if (p_ev.type==InputEvent::MOUSE_BUTTON && p_ev.mouse_button.button_index==BUTTON_LEFT && p_ev.mouse_button.pressed) { Ref<Texture> port =get_icon("port","GraphNode"); Vector2 mpos(p_ev.mouse_button.x,p_ev.mouse_button.y); - float grab_r=port->get_width()*0.5; + float grab_r=port->get_width()*0.5*grab_r_extend; for(int i=get_child_count()-1;i>=0;i--) { GraphNode *gn=get_child(i)->cast_to<GraphNode>(); @@ -295,6 +412,37 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { Vector2 pos = gn->get_connection_output_pos(j)+gn->get_pos(); if (pos.distance_to(mpos)<grab_r) { + + if (valid_left_disconnect_types.has(gn->get_connection_output_type(j))) { + //check disconnect + for (List<Connection>::Element*E=connections.front();E;E=E->next()) { + + if (E->get().from==gn->get_name() && E->get().from_port==j) { + + Node*to = get_node(String(E->get().to)); + if (to && to->cast_to<GraphNode>()) { + + connecting_from=E->get().to; + connecting_index=E->get().to_port; + connecting_out=false; + connecting_type=to->cast_to<GraphNode>()->get_connection_input_type(E->get().to_port); + connecting_color=to->cast_to<GraphNode>()->get_connection_input_color(E->get().to_port); + connecting_target=false; + connecting_to=pos; + just_disconected=true; + + emit_signal("disconnection_request",E->get().from,E->get().from_port,E->get().to,E->get().to_port); + to = get_node(String(connecting_from)); //maybe it was erased + if (to && to->cast_to<GraphNode>()) { + connecting=true; + } + return; + } + + } + } + } + connecting=true; connecting_from=gn->get_name(); connecting_index=j; @@ -303,6 +451,7 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { connecting_color=gn->get_connection_output_color(j); connecting_target=false; connecting_to=pos; + just_disconected=false; return; } @@ -315,7 +464,7 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { if (pos.distance_to(mpos)<grab_r) { - if (right_disconnects) { + if (right_disconnects || valid_right_disconnect_types.has(gn->get_connection_input_type(j))) { //check disconnect for (List<Connection>::Element*E=connections.front();E;E=E->next()) { @@ -331,6 +480,7 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { connecting_color=fr->cast_to<GraphNode>()->get_connection_output_color(E->get().from_port); connecting_target=false; connecting_to=pos; + just_disconected=true; emit_signal("disconnection_request",E->get().from,E->get().from_port,E->get().to,E->get().to_port); fr = get_node(String(connecting_from)); //maybe it was erased @@ -353,6 +503,8 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { connecting_color=gn->get_connection_input_color(j); connecting_target=false; connecting_to=pos; + just_disconected=true; + return; } @@ -365,11 +517,11 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { connecting_to=Vector2(p_ev.mouse_motion.x,p_ev.mouse_motion.y); connecting_target=false; - top_layer->update(); + top_layer->update(); Ref<Texture> port =get_icon("port","GraphNode"); Vector2 mpos(p_ev.mouse_button.x,p_ev.mouse_button.y); - float grab_r=port->get_width()*0.5; + float grab_r=port->get_width()*0.5*grab_r_extend; for(int i=get_child_count()-1;i>=0;i--) { GraphNode *gn=get_child(i)->cast_to<GraphNode>(); @@ -381,7 +533,7 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { Vector2 pos = gn->get_connection_output_pos(j)+gn->get_pos(); int type =gn->get_connection_output_type(j); - if (type==connecting_type && pos.distance_to(mpos)<grab_r) { + if ((type==connecting_type ||valid_connection_types.has(ConnType(type,connecting_type))) && pos.distance_to(mpos)<grab_r) { connecting_target=true; connecting_to=pos; @@ -398,7 +550,7 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { Vector2 pos = gn->get_connection_input_pos(j)+gn->get_pos(); int type =gn->get_connection_input_type(j); - if (type==connecting_type && pos.distance_to(mpos)<grab_r) { + if ((type==connecting_type ||valid_connection_types.has(ConnType(type,connecting_type))) && pos.distance_to(mpos)<grab_r) { connecting_target=true; connecting_to=pos; connecting_target_to=gn->get_name(); @@ -425,18 +577,91 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { } emit_signal("connection_request",from,from_slot,to,to_slot); + } else if (!just_disconected) { + String from = connecting_from; + int from_slot = connecting_index; + Vector2 ofs = Vector2(p_ev.mouse_button.x,p_ev.mouse_button.y); + emit_signal("connection_to_empty",from,from_slot,ofs); } connecting=false; top_layer->update(); + update(); + connections_layer->update(); } } -void GraphEdit::_draw_cos_line(const Vector2& p_from, const Vector2& p_to,const Color& p_color) { + +template<class Vector2> +static _FORCE_INLINE_ Vector2 _bezier_interp(real_t t, Vector2 start, Vector2 control_1, Vector2 control_2, Vector2 end) { + /* Formula from Wikipedia article on Bezier curves. */ + real_t omt = (1.0 - t); + real_t omt2 = omt*omt; + real_t omt3 = omt2*omt; + real_t t2 = t*t; + real_t t3 = t2*t; + + return start * omt3 + + control_1 * omt2 * t * 3.0 + + control_2 * omt * t2 * 3.0 + + end * t3; +} + + +void GraphEdit::_bake_segment2d(CanvasItem* p_where,float p_begin, float p_end,const Vector2& p_a,const Vector2& p_out,const Vector2& p_b, const Vector2& p_in,int p_depth,int p_min_depth,int p_max_depth,float p_tol,const Color& p_color,const Color& p_to_color,int &lines) const { + + float mp = p_begin+(p_end-p_begin)*0.5; + Vector2 beg = _bezier_interp(p_begin,p_a,p_a+p_out,p_b+p_in,p_b); + Vector2 mid = _bezier_interp(mp,p_a,p_a+p_out,p_b+p_in,p_b); + Vector2 end = _bezier_interp(p_end,p_a,p_a+p_out,p_b+p_in,p_b); + + Vector2 na = (mid-beg).normalized(); + Vector2 nb = (end-mid).normalized(); + float dp = Math::rad2deg(Math::acos(na.dot(nb))); + + if (p_depth>=p_min_depth && ( dp<p_tol || p_depth>=p_max_depth)) { + + + + p_where->draw_line(beg,end,p_color.linear_interpolate(p_to_color,mp),2,true); + lines++; + } else { + _bake_segment2d(p_where,p_begin,mp,p_a,p_out,p_b,p_in,p_depth+1,p_min_depth,p_max_depth,p_tol,p_color,p_to_color,lines); + _bake_segment2d(p_where,mp,p_end,p_a,p_out,p_b,p_in,p_depth+1,p_min_depth,p_max_depth,p_tol,p_color,p_to_color,lines); + } +} + + +void GraphEdit::_draw_cos_line(CanvasItem* p_where,const Vector2& p_from, const Vector2& p_to,const Color& p_color,const Color& p_to_color) { + + +#if 1 + + //cubic bezier code + float diff = p_to.x-p_from.x; + float cp_offset; + int cp_len = get_constant("bezier_len_pos"); + int cp_neg_len = get_constant("bezier_len_neg"); + + if (diff>0) { + cp_offset=MAX(cp_len,diff*0.5); + } else { + cp_offset=MAX(MIN(cp_len-diff,cp_neg_len),-diff*0.5); + } + + Vector2 c1 = Vector2(cp_offset,0); + Vector2 c2 = Vector2(-cp_offset,0); + + int lines=0; + _bake_segment2d(p_where,0,1,p_from,c1,p_to,c2,0,3,9,8,p_color,p_to_color,lines); + + +#else static const int steps = 20; + //old cosine code Rect2 r; r.pos=p_from; r.expand_to(p_to); @@ -446,6 +671,7 @@ void GraphEdit::_draw_cos_line(const Vector2& p_from, const Vector2& p_to,const Vector2 prev; for(int i=0;i<=steps;i++) { + float d = i/float(steps); float c=-Math::cos(d*Math_PI) * 0.5+0.5; if (flip) @@ -454,11 +680,65 @@ void GraphEdit::_draw_cos_line(const Vector2& p_from, const Vector2& p_to,const if (i>0) { - top_layer->draw_line(prev,p,p_color,2); + p_where->draw_line(prev,p,p_color.linear_interpolate(p_to_color,d),2); } prev=p; } +#endif +} + + +void GraphEdit::_connections_layer_draw() { + + + { + //draw connections + List<List<Connection>::Element* > to_erase; + for(List<Connection>::Element *E=connections.front();E;E=E->next()) { + + NodePath fromnp(E->get().from); + + Node * from = get_node(fromnp); + if (!from) { + to_erase.push_back(E); + continue; + } + + GraphNode *gfrom = from->cast_to<GraphNode>(); + + if (!gfrom) { + to_erase.push_back(E); + continue; + } + + NodePath tonp(E->get().to); + Node * to = get_node(tonp); + if (!to) { + to_erase.push_back(E); + continue; + } + + GraphNode *gto = to->cast_to<GraphNode>(); + + if (!gto) { + to_erase.push_back(E); + continue; + } + + Vector2 frompos=gfrom->get_connection_output_pos(E->get().from_port)+gfrom->get_offset(); + Color color = gfrom->get_connection_output_color(E->get().from_port); + Vector2 topos=gto->get_connection_input_pos(E->get().to_port)+gto->get_offset(); + Color tocolor = gto->get_connection_input_color(E->get().to_port); + _draw_cos_line(connections_layer,frompos,topos,color,tocolor); + + } + + while(to_erase.size()) { + connections.erase(to_erase.front()->get()); + to_erase.pop_front(); + } + } } void GraphEdit::_top_layer_draw() { @@ -488,54 +768,28 @@ void GraphEdit::_top_layer_draw() { col.g+=0.4; col.b+=0.4; } - _draw_cos_line(pos,topos,col); - } - List<List<Connection>::Element* > to_erase; - for(List<Connection>::Element *E=connections.front();E;E=E->next()) { - - NodePath fromnp(E->get().from); - - Node * from = get_node(fromnp); - if (!from) { - to_erase.push_back(E); - continue; + if (!connecting_out) { + SWAP(pos,topos); } + _draw_cos_line(top_layer,pos,topos,col,col); + } - GraphNode *gfrom = from->cast_to<GraphNode>(); - if (!gfrom) { - to_erase.push_back(E); - continue; - } + if (box_selecting) + top_layer->draw_rect(box_selecting_rect,Color(0.7,0.7,1.0,0.3)); +} - NodePath tonp(E->get().to); - Node * to = get_node(tonp); - if (!to) { - to_erase.push_back(E); - continue; - } +void GraphEdit::set_selected(Node* p_child) { - GraphNode *gto = to->cast_to<GraphNode>(); + for(int i=get_child_count()-1;i>=0;i--) { - if (!gto) { - to_erase.push_back(E); + GraphNode *gn=get_child(i)->cast_to<GraphNode>(); + if (!gn) continue; - } - - Vector2 frompos=gfrom->get_connection_output_pos(E->get().from_port)+gfrom->get_pos(); - Color color = gfrom->get_connection_output_color(E->get().from_port); - Vector2 topos=gto->get_connection_input_pos(E->get().to_port)+gto->get_pos(); - _draw_cos_line(frompos,topos,color); + gn->set_selected(gn==p_child); } - - while(to_erase.size()) { - connections.erase(to_erase.front()->get()); - to_erase.pop_front(); - } - if (box_selecting) - top_layer->draw_rect(box_selecting_rect,Color(0.7,0.7,1.0,0.3)); } void GraphEdit::_input_event(const InputEvent& p_ev) { @@ -548,11 +802,21 @@ void GraphEdit::_input_event(const InputEvent& p_ev) { if (p_ev.type==InputEvent::MOUSE_MOTION && dragging) { just_selected=true; - drag_accum+=Vector2(p_ev.mouse_motion.relative_x,p_ev.mouse_motion.relative_y); + // TODO: Remove local mouse pos hack if/when InputEventMouseMotion is fixed to support floats + //drag_accum+=Vector2(p_ev.mouse_motion.relative_x,p_ev.mouse_motion.relative_y); + drag_accum = get_local_mouse_pos() - drag_origin; for(int i=get_child_count()-1;i>=0;i--) { GraphNode *gn=get_child(i)->cast_to<GraphNode>(); - if (gn && gn->is_selected()) - gn->set_offset((gn->get_drag_from()*zoom+drag_accum)/zoom); + if (gn && gn->is_selected()) { + + Vector2 pos = (gn->get_drag_from()*zoom+drag_accum)/zoom; + if (is_using_snap()) { + int snap = get_snap(); + pos = pos.snapped(Vector2(snap,snap)); + } + + gn->set_offset(pos); + } } } @@ -641,6 +905,8 @@ void GraphEdit::_input_event(const InputEvent& p_ev) { dragging = false; top_layer->update(); + update(); + connections_layer->update(); } if (b.button_index==BUTTON_LEFT && b.pressed) { @@ -651,6 +917,10 @@ void GraphEdit::_input_event(const InputEvent& p_ev) { gn=get_child(i)->cast_to<GraphNode>(); if (gn) { + + if (gn->is_resizing()) + continue; + Rect2 r = gn->get_rect(); r.size*=zoom; if (r.has_point(get_local_mouse_pos())) @@ -665,6 +935,7 @@ void GraphEdit::_input_event(const InputEvent& p_ev) { dragging = true; drag_accum = Vector2(); + drag_origin = get_local_mouse_pos(); just_selected = !gn->is_selected(); if(!gn->is_selected() && !Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { for (int i = 0; i < get_child_count(); i++) { @@ -761,6 +1032,7 @@ void GraphEdit::clear_connections() { connections.clear(); update(); + connections_layer->update(); } void GraphEdit::set_zoom(float p_zoom) { @@ -804,6 +1076,29 @@ bool GraphEdit::is_right_disconnects_enabled() const{ return right_disconnects; } +void GraphEdit::add_valid_right_disconnect_type(int p_type) { + + valid_right_disconnect_types.insert(p_type); +} + +void GraphEdit::remove_valid_right_disconnect_type(int p_type){ + + valid_right_disconnect_types.erase(p_type); + +} + +void GraphEdit::add_valid_left_disconnect_type(int p_type){ + + valid_left_disconnect_types.insert(p_type); + +} + +void GraphEdit::remove_valid_left_disconnect_type(int p_type){ + + valid_left_disconnect_types.erase(p_type); + +} + Array GraphEdit::_get_connection_list() const { List<Connection> conns; @@ -838,6 +1133,68 @@ void GraphEdit::_zoom_plus() { set_zoom(zoom*ZOOM_SCALE); } +void GraphEdit::add_valid_connection_type(int p_type,int p_with_type) { + + ConnType ct; + ct.type_a=p_type; + ct.type_b=p_with_type; + + valid_connection_types.insert(ct); +} + +void GraphEdit::remove_valid_connection_type(int p_type,int p_with_type) { + + ConnType ct; + ct.type_a=p_type; + ct.type_b=p_with_type; + + valid_connection_types.erase(ct); + +} + +bool GraphEdit::is_valid_connection_type(int p_type,int p_with_type) const { + + ConnType ct; + ct.type_a=p_type; + ct.type_b=p_with_type; + + return valid_connection_types.has(ct); + +} + +void GraphEdit::set_use_snap(bool p_enable) { + + snap_button->set_pressed(p_enable); + update(); + +} + +bool GraphEdit::is_using_snap() const{ + + return snap_button->is_pressed(); + +} + +int GraphEdit::get_snap() const{ + + return snap_amount->get_val(); +} + +void GraphEdit::set_snap(int p_snap) { + + ERR_FAIL_COND(p_snap<5); + snap_amount->set_val(p_snap); + update(); +} +void GraphEdit::_snap_toggled() { + update(); +} + +void GraphEdit::_snap_value_changed(double) { + + update(); +} + void GraphEdit::_bind_methods() { @@ -846,10 +1203,17 @@ void GraphEdit::_bind_methods() { ObjectTypeDB::bind_method(_MD("disconnect_node","from","from_port","to","to_port"),&GraphEdit::disconnect_node); ObjectTypeDB::bind_method(_MD("get_connection_list"),&GraphEdit::_get_connection_list); ObjectTypeDB::bind_method(_MD("get_scroll_ofs"),&GraphEdit::get_scroll_ofs); + ObjectTypeDB::bind_method(_MD("set_scroll_ofs","ofs"),&GraphEdit::set_scroll_ofs); ObjectTypeDB::bind_method(_MD("set_zoom","p_zoom"),&GraphEdit::set_zoom); ObjectTypeDB::bind_method(_MD("get_zoom"),&GraphEdit::get_zoom); + ObjectTypeDB::bind_method(_MD("set_snap","pixels"),&GraphEdit::set_snap); + ObjectTypeDB::bind_method(_MD("get_snap"),&GraphEdit::get_snap); + + ObjectTypeDB::bind_method(_MD("set_use_snap","enable"),&GraphEdit::set_use_snap); + ObjectTypeDB::bind_method(_MD("is_using_snap"),&GraphEdit::is_using_snap); + ObjectTypeDB::bind_method(_MD("set_right_disconnects","enable"),&GraphEdit::set_right_disconnects); ObjectTypeDB::bind_method(_MD("is_right_disconnects_enabled"),&GraphEdit::is_right_disconnects_enabled); @@ -862,16 +1226,27 @@ void GraphEdit::_bind_methods() { ObjectTypeDB::bind_method(_MD("_zoom_minus"),&GraphEdit::_zoom_minus); ObjectTypeDB::bind_method(_MD("_zoom_reset"),&GraphEdit::_zoom_reset); ObjectTypeDB::bind_method(_MD("_zoom_plus"),&GraphEdit::_zoom_plus); + ObjectTypeDB::bind_method(_MD("_snap_toggled"),&GraphEdit::_snap_toggled); + ObjectTypeDB::bind_method(_MD("_snap_value_changed"),&GraphEdit::_snap_value_changed); ObjectTypeDB::bind_method(_MD("_input_event"),&GraphEdit::_input_event); + ObjectTypeDB::bind_method(_MD("_update_scroll_offset"),&GraphEdit::_update_scroll_offset); + ObjectTypeDB::bind_method(_MD("_connections_layer_draw"),&GraphEdit::_connections_layer_draw); + + + + ObjectTypeDB::bind_method(_MD("set_selected","node"),&GraphEdit::set_selected); ADD_SIGNAL(MethodInfo("connection_request",PropertyInfo(Variant::STRING,"from"),PropertyInfo(Variant::INT,"from_slot"),PropertyInfo(Variant::STRING,"to"),PropertyInfo(Variant::INT,"to_slot"))); ADD_SIGNAL(MethodInfo("disconnection_request",PropertyInfo(Variant::STRING,"from"),PropertyInfo(Variant::INT,"from_slot"),PropertyInfo(Variant::STRING,"to"),PropertyInfo(Variant::INT,"to_slot"))); ADD_SIGNAL(MethodInfo("popup_request", PropertyInfo(Variant::VECTOR2,"p_position"))); ADD_SIGNAL(MethodInfo("duplicate_nodes_request")); + ADD_SIGNAL(MethodInfo("node_selected",PropertyInfo(Variant::OBJECT,"node"))); + ADD_SIGNAL(MethodInfo("connection_to_empty",PropertyInfo(Variant::STRING,"from"),PropertyInfo(Variant::INT,"from_slot"),PropertyInfo(Variant::VECTOR2,"release_pos"))); ADD_SIGNAL(MethodInfo("delete_nodes_request")); ADD_SIGNAL(MethodInfo("_begin_node_move")); ADD_SIGNAL(MethodInfo("_end_node_move")); + ADD_SIGNAL(MethodInfo("scroll_offset_changed",PropertyInfo(Variant::VECTOR2,"ofs"))); } @@ -879,6 +1254,7 @@ void GraphEdit::_bind_methods() { GraphEdit::GraphEdit() { set_focus_mode(FOCUS_ALL); + awaiting_scroll_offset_update=false; top_layer=NULL; top_layer=memnew(GraphEditFilter(this)); add_child(top_layer); @@ -888,6 +1264,12 @@ GraphEdit::GraphEdit() { top_layer->set_stop_mouse(false); top_layer->connect("input_event",this,"_top_layer_input"); + connections_layer = memnew( Control ); + add_child(connections_layer); + connections_layer->connect("draw",this,"_connections_layer_draw"); + connections_layer->set_name("CLAYER"); + connections_layer->set_disable_visibility_clip(true); // so it can draw freely and be offseted + h_scroll = memnew(HScrollBar); h_scroll->set_name("_h_scroll"); top_layer->add_child(h_scroll); @@ -902,6 +1284,13 @@ GraphEdit::GraphEdit() { box_selecting = false; dragging = false; + //set large minmax so it can scroll even if not resized yet + h_scroll->set_min(-10000); + h_scroll->set_max(10000); + + v_scroll->set_min(-10000); + v_scroll->set_max(10000); + h_scroll->connect("value_changed", this,"_scroll_moved"); v_scroll->connect("value_changed", this,"_scroll_moved"); @@ -915,17 +1304,36 @@ GraphEdit::GraphEdit() { zoom_minus = memnew( ToolButton ); zoom_hb->add_child(zoom_minus); zoom_minus->connect("pressed",this,"_zoom_minus"); - zoom_minus->set_icon(get_icon("minus")); + zoom_minus->set_focus_mode(FOCUS_NONE); zoom_reset = memnew( ToolButton ); zoom_hb->add_child(zoom_reset); zoom_reset->connect("pressed",this,"_zoom_reset"); - zoom_reset->set_icon(get_icon("reset")); + zoom_reset->set_focus_mode(FOCUS_NONE); zoom_plus = memnew( ToolButton ); zoom_hb->add_child(zoom_plus); zoom_plus->connect("pressed",this,"_zoom_plus"); - zoom_plus->set_icon(get_icon("more")); + zoom_plus->set_focus_mode(FOCUS_NONE); + + snap_button = memnew( ToolButton ); + snap_button->set_toggle_mode(true); + snap_button->connect("pressed",this,"_snap_toggled"); + snap_button->set_pressed(true); + snap_button->set_focus_mode(FOCUS_NONE); + zoom_hb->add_child(snap_button); + + snap_amount = memnew( SpinBox ); + snap_amount->set_min(5); + snap_amount->set_max(100); + snap_amount->set_step(1); + snap_amount->set_val(20); + snap_amount->connect("value_changed",this,"_snap_value_changed"); + zoom_hb->add_child(snap_amount); + + setting_scroll_ofs=false; + just_disconected=false; + } diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index ac4e71ba49..c5174f6699 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -33,6 +33,7 @@ #include "scene/gui/scroll_bar.h" #include "scene/gui/slider.h" #include "scene/gui/tool_button.h" +#include "scene/gui/spin_box.h" #include "texture_frame.h" class GraphEdit; @@ -70,6 +71,9 @@ private: ToolButton *zoom_reset; ToolButton *zoom_plus; + ToolButton *snap_button; + SpinBox *snap_amount; + void _zoom_minus(); void _zoom_reset(); void _zoom_plus(); @@ -88,10 +92,12 @@ private: Vector2 connecting_to; String connecting_target_to; int connecting_target_index; + bool just_disconected; bool dragging; bool just_selected; Vector2 drag_accum; + Point2 drag_origin; // Workaround for GH-5907 float zoom; @@ -102,11 +108,15 @@ private: Rect2 box_selecting_rect; List<GraphNode*> previus_selected; + bool setting_scroll_ofs; bool right_disconnects; bool updating; + bool awaiting_scroll_offset_update; List<Connection> connections; - void _draw_cos_line(const Vector2& p_from, const Vector2& p_to,const Color& p_color); + void _bake_segment2d(CanvasItem* p_where,float p_begin, float p_end, const Vector2& p_a, const Vector2& p_out, const Vector2& p_b, const Vector2& p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color& p_color, const Color& p_to_color, int &lines) const; + + void _draw_cos_line(CanvasItem* p_where,const Vector2& p_from, const Vector2& p_to, const Color& p_color, const Color &p_to_color); void _graph_node_raised(Node* p_gn); void _graph_node_moved(Node *p_gn); @@ -115,15 +125,47 @@ private: void _scroll_moved(double); void _input_event(const InputEvent& p_ev); + Control *connections_layer; GraphEditFilter *top_layer; void _top_layer_input(const InputEvent& p_ev); void _top_layer_draw(); + void _connections_layer_draw(); void _update_scroll_offset(); Array _get_connection_list() const; + bool lines_on_bg; + + + + struct ConnType { + + union { + struct { + uint32_t type_a; + uint32_t type_b; + }; + uint64_t key; + }; + + bool operator<(const ConnType& p_type) const { + return key<p_type.key; + } + + ConnType(uint32_t a=0, uint32_t b=0) { + type_a=a; + type_b=b; + } + }; + + Set<ConnType> valid_connection_types; + Set<int> valid_left_disconnect_types; + Set<int> valid_right_disconnect_types; + friend class GraphEditFilter; bool _filter_input(const Point2& p_point); + void _snap_toggled(); + void _snap_value_changed(double); protected: static void _bind_methods(); @@ -138,6 +180,10 @@ public: void disconnect_node(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port); void clear_connections(); + void add_valid_connection_type(int p_type,int p_with_type); + void remove_valid_connection_type(int p_type,int p_with_type); + bool is_valid_connection_type(int p_type,int p_with_type) const; + void set_zoom(float p_zoom); float get_zoom() const; @@ -147,8 +193,23 @@ public: void set_right_disconnects(bool p_enable); bool is_right_disconnects_enabled() const; + void add_valid_right_disconnect_type(int p_type); + void remove_valid_right_disconnect_type(int p_type); + + void add_valid_left_disconnect_type(int p_type); + void remove_valid_left_disconnect_type(int p_type); + + void set_scroll_ofs(const Vector2& p_ofs); Vector2 get_scroll_ofs() const; + void set_selected(Node* p_child); + + void set_use_snap(bool p_enable); + bool is_using_snap() const; + + int get_snap() const; + void set_snap(int p_snap); + GraphEdit(); }; diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index 94001b2ac1..da298a795a 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -183,14 +183,45 @@ void GraphNode::_resort() { } +bool GraphNode::has_point(const Point2& p_point) const { + + if (comment) { + Ref<StyleBox> comment = get_stylebox("comment"); + Ref<Texture> resizer =get_icon("resizer"); + + if (Rect2(get_size()-resizer->get_size(), resizer->get_size()).has_point(p_point)) { + return true; + } + if (Rect2(0,0,get_size().width,comment->get_margin(MARGIN_TOP)).has_point(p_point)) { + return true; + } + + return false; + + } else { + return Control::has_point(p_point); + } +} void GraphNode::_notification(int p_what) { if (p_what==NOTIFICATION_DRAW) { - Ref<StyleBox> sb=get_stylebox(selected ? "selectedframe" : "frame"); + Ref<StyleBox> sb; + + if (comment) { + sb = get_stylebox( selected? "commentfocus" : "comment"); + + } else { + + sb = get_stylebox( selected ? "selectedframe" : "frame"); + } + + sb=sb->duplicate(); + sb->call("set_modulate",modulate); Ref<Texture> port =get_icon("port"); Ref<Texture> close =get_icon("close"); + Ref<Texture> resizer =get_icon("resizer"); int close_offset = get_constant("close_offset"); Ref<Font> title_font = get_font("title_font"); int title_offset = get_constant("title_offset"); @@ -198,8 +229,25 @@ void GraphNode::_notification(int p_what) { Point2i icofs = -port->get_size()*0.5; int edgeofs=get_constant("port_offset"); icofs.y+=sb->get_margin(MARGIN_TOP); + + + draw_style_box(sb,Rect2(Point2(),get_size())); + switch(overlay) { + case OVERLAY_DISABLED: { + + } break; + case OVERLAY_BREAKPOINT: { + + draw_style_box(get_stylebox("breakpoint"),Rect2(Point2(),get_size())); + } break; + case OVERLAY_POSITION: { + draw_style_box(get_stylebox("position"),Rect2(Point2(),get_size())); + + } break; + } + int w = get_size().width-sb->get_minimum_size().x; if (show_close) @@ -223,11 +271,26 @@ void GraphNode::_notification(int p_what) { continue; const Slot &s=slot_info[E->key()]; //left - if (s.enable_left) - port->draw(get_canvas_item(),icofs+Point2(edgeofs,cache_y[E->key()]),s.color_left); - if (s.enable_right) - port->draw(get_canvas_item(),icofs+Point2(get_size().x-edgeofs,cache_y[E->key()]),s.color_right); + if (s.enable_left) { + Ref<Texture> p = port; + if (s.custom_slot_left.is_valid()) { + p=s.custom_slot_left; + } + p->draw(get_canvas_item(),icofs+Point2(edgeofs,cache_y[E->key()]),s.color_left); + } + if (s.enable_right) { + Ref<Texture> p = port; + if (s.custom_slot_right.is_valid()) { + p=s.custom_slot_right; + } + p->draw(get_canvas_item(),icofs+Point2(get_size().x-edgeofs,cache_y[E->key()]),s.color_right); + } + + } + + if (resizeable) { + draw_texture(resizer,get_size()-resizer->get_size()); } } @@ -239,7 +302,7 @@ void GraphNode::_notification(int p_what) { } -void GraphNode::set_slot(int p_idx,bool p_enable_left,int p_type_left,const Color& p_color_left, bool p_enable_right,int p_type_right,const Color& p_color_right) { +void GraphNode::set_slot(int p_idx,bool p_enable_left,int p_type_left,const Color& p_color_left, bool p_enable_right,int p_type_right,const Color& p_color_right,const Ref<Texture>& p_custom_left,const Ref<Texture>& p_custom_right) { ERR_FAIL_COND(p_idx<0); @@ -255,6 +318,8 @@ void GraphNode::set_slot(int p_idx,bool p_enable_left,int p_type_left,const Colo s.enable_right=p_enable_right; s.type_right=p_type_right; s.color_right=p_color_right; + s.custom_slot_left=p_custom_left; + s.custom_slot_right=p_custom_right; slot_info[p_idx]=s; update(); connpos_dirty=true; @@ -559,18 +624,99 @@ Color GraphNode::get_connection_output_color(int p_idx) { void GraphNode::_input_event(const InputEvent& p_ev) { if (p_ev.type==InputEvent::MOUSE_BUTTON) { - get_parent_control()->grab_focus(); + + ERR_EXPLAIN("GraphNode must be the child of a GraphEdit node."); + ERR_FAIL_COND(get_parent_control() == NULL); + + print_line("INPUT EVENT BUTTON"); + 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); if (close_rect.size!=Size2() && close_rect.has_point(mpos)) { emit_signal("close_request"); + accept_event(); return; } + + Ref<Texture> resizer =get_icon("resizer"); + + if (resizeable && mpos.x > get_size().x-resizer->get_width() && mpos.y > get_size().y-resizer->get_height()) { + + resizing=true; + resizing_from=mpos; + resizing_from_size=get_size(); + accept_event(); + return; + } + + //send focus to parent emit_signal("raise_request"); + get_parent_control()->grab_focus(); + } + + if(!p_ev.mouse_button.pressed && p_ev.mouse_button.button_index==BUTTON_LEFT) { + resizing=false; + } + } + + if (resizing && p_ev.type==InputEvent::MOUSE_MOTION) { + Vector2 mpos = Vector2(p_ev.mouse_motion.x,p_ev.mouse_motion.y); + + Vector2 diff = mpos - resizing_from; + + emit_signal("resize_request",resizing_from_size+diff); + + } + + +} + +void GraphNode::set_modulate(const Color &p_color) { + + modulate=p_color; + update(); +} + +Color GraphNode::get_modulate() const{ + + return modulate; +} +void GraphNode::set_overlay(Overlay p_overlay) { + + overlay=p_overlay; + update(); +} + +GraphNode::Overlay GraphNode::get_overlay() const{ + + return overlay; +} + +void GraphNode::set_comment(bool p_enable) { + + comment=p_enable; + update(); +} + +bool GraphNode::is_comment() const{ + + return comment; +} + + +void GraphNode::set_resizeable(bool p_enable) { + + resizeable=p_enable; + update(); +} + +bool GraphNode::is_resizeable() const{ + + return resizeable; } @@ -580,7 +726,7 @@ void GraphNode::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_title"),&GraphNode::get_title); ObjectTypeDB::bind_method(_MD("_input_event"),&GraphNode::_input_event); - ObjectTypeDB::bind_method(_MD("set_slot","idx","enable_left","type_left","color_left","enable_right","type_right","color_right"),&GraphNode::set_slot); + ObjectTypeDB::bind_method(_MD("set_slot","idx","enable_left","type_left","color_left","enable_right","type_right","color_right","custom_left","custom_right"),&GraphNode::set_slot,DEFVAL(Ref<Texture>()),DEFVAL(Ref<Texture>())); ObjectTypeDB::bind_method(_MD("clear_slot","idx"),&GraphNode::clear_slot); ObjectTypeDB::bind_method(_MD("clear_all_slots","idx"),&GraphNode::clear_all_slots); ObjectTypeDB::bind_method(_MD("is_slot_enabled_left","idx"),&GraphNode::is_slot_enabled_left); @@ -593,6 +739,12 @@ void GraphNode::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_offset","offset"),&GraphNode::set_offset); ObjectTypeDB::bind_method(_MD("get_offset"),&GraphNode::get_offset); + ObjectTypeDB::bind_method(_MD("set_comment","comment"),&GraphNode::set_comment); + ObjectTypeDB::bind_method(_MD("is_comment"),&GraphNode::is_comment); + + ObjectTypeDB::bind_method(_MD("set_resizeable","resizeable"),&GraphNode::set_resizeable); + ObjectTypeDB::bind_method(_MD("is_resizeable"),&GraphNode::is_resizeable); + ObjectTypeDB::bind_method(_MD("get_connection_output_count"),&GraphNode::get_connection_output_count); ObjectTypeDB::bind_method(_MD("get_connection_input_count"),&GraphNode::get_connection_input_count); @@ -603,10 +755,15 @@ void GraphNode::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_connection_input_type","idx"),&GraphNode::get_connection_input_type); ObjectTypeDB::bind_method(_MD("get_connection_input_color","idx"),&GraphNode::get_connection_input_color); + ObjectTypeDB::bind_method(_MD("set_modulate","color"),&GraphNode::set_modulate); + ObjectTypeDB::bind_method(_MD("get_modulate"),&GraphNode::get_modulate); ObjectTypeDB::bind_method(_MD("set_show_close_button","show"),&GraphNode::set_show_close_button); ObjectTypeDB::bind_method(_MD("is_close_button_visible"),&GraphNode::is_close_button_visible); + ObjectTypeDB::bind_method(_MD("set_overlay","overlay"),&GraphNode::set_overlay); + ObjectTypeDB::bind_method(_MD("get_overlay"),&GraphNode::get_overlay); + ADD_PROPERTY( PropertyInfo(Variant::STRING,"title"),_SCS("set_title"),_SCS("get_title")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"show_close"),_SCS("set_show_close_button"),_SCS("is_close_button_visible")); @@ -614,10 +771,21 @@ void GraphNode::_bind_methods() { ADD_SIGNAL(MethodInfo("dragged",PropertyInfo(Variant::VECTOR2,"from"),PropertyInfo(Variant::VECTOR2,"to"))); ADD_SIGNAL(MethodInfo("raise_request")); ADD_SIGNAL(MethodInfo("close_request")); + ADD_SIGNAL(MethodInfo("resize_request",PropertyInfo(Variant::VECTOR2,"new_minsize"))); + + BIND_CONSTANT( OVERLAY_DISABLED ); + BIND_CONSTANT( OVERLAY_BREAKPOINT ); + BIND_CONSTANT( OVERLAY_POSITION ); } GraphNode::GraphNode() { + + overlay=OVERLAY_DISABLED; show_close=false; connpos_dirty=true; set_stop_mouse(false); + modulate=Color(1,1,1,1); + comment=false; + resizeable=false; + resizing=false; } diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h index 5a50d0d68d..cbfd34f556 100644 --- a/scene/gui/graph_node.h +++ b/scene/gui/graph_node.h @@ -34,8 +34,14 @@ class GraphNode : public Container { OBJ_TYPE(GraphNode,Container); +public: - + enum Overlay { + OVERLAY_DISABLED, + OVERLAY_BREAKPOINT, + OVERLAY_POSITION + }; +private: struct Slot { bool enable_left; @@ -44,6 +50,8 @@ class GraphNode : public Container { bool enable_right; int type_right; Color color_right; + Ref<Texture> custom_slot_left; + Ref<Texture> custom_slot_right; Slot() { enable_left=false; type_left=0; color_left=Color(1,1,1,1); enable_right=false; type_right=0; color_right=Color(1,1,1,1); } @@ -52,6 +60,12 @@ class GraphNode : public Container { String title; bool show_close; Vector2 offset; + bool comment; + bool resizeable; + + bool resizing; + Vector2 resizing_from; + Vector2 resizing_from_size; Rect2 close_rect; @@ -75,6 +89,13 @@ class GraphNode : public Container { Vector2 drag_from; bool selected; + + Overlay overlay; + + Color modulate; + + bool has_point(const Point2& p_point) const; + protected: @@ -91,7 +112,7 @@ public: - void set_slot(int p_idx,bool p_enable_left,int p_type_left,const Color& p_color_left, bool p_enable_right,int p_type_right,const Color& p_color_right); + void set_slot(int p_idx,bool p_enable_left,int p_type_left,const Color& p_color_left, bool p_enable_right,int p_type_right,const Color& p_color_right,const Ref<Texture>& p_custom_left=Ref<Texture>(),const Ref<Texture>& p_custom_right=Ref<Texture>()); void clear_slot(int p_idx); void clear_all_slots(); bool is_slot_enabled_left(int p_idx) const; @@ -126,10 +147,25 @@ public: Color get_connection_output_color(int p_idx); + void set_modulate(const Color& p_color); + Color get_modulate() const; + + void set_overlay(Overlay p_overlay); + Overlay get_overlay() const; + + void set_comment(bool p_enable); + bool is_comment() const; + + void set_resizeable(bool p_enable); + bool is_resizeable() const; + virtual Size2 get_minimum_size() const; + bool is_resizing() const { return resizing; } + GraphNode(); }; +VARIANT_ENUM_CAST( GraphNode::Overlay ) #endif // GRAPH_NODE_H diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index d63c483ef9..89cd509fbd 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -40,6 +40,7 @@ void ItemList::add_item(const String& p_item,const Ref<Texture>& p_texture,bool item.selectable=p_selectable; item.selected=false; item.disabled=false; + item.tooltip_enabled=true; item.custom_bg=Color(0,0,0,0); items.push_back(item); @@ -57,6 +58,7 @@ void ItemList::add_icon_item(const Ref<Texture>& p_item,bool p_selectable){ item.selectable=p_selectable; item.selected=false; item.disabled=false; + item.tooltip_enabled=true; item.custom_bg=Color(0,0,0,0); items.push_back(item); @@ -82,6 +84,16 @@ String ItemList::get_item_text(int p_idx) const{ } +void ItemList::set_item_tooltip_enabled(int p_idx, const bool p_enabled) { + ERR_FAIL_INDEX(p_idx,items.size()); + items[p_idx].tooltip_enabled = p_enabled; +} + +bool ItemList::is_item_tooltip_enabled(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx,items.size(), false); + return items[p_idx].tooltip_enabled; +} + void ItemList::set_item_tooltip(int p_idx,const String& p_tooltip){ ERR_FAIL_INDEX(p_idx,items.size()); @@ -191,7 +203,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 +237,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 +249,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 +348,7 @@ void ItemList::clear(){ current=-1; ensure_selected_visible=false; update(); + shape_changed=true; defer_select_single=-1; } @@ -461,7 +474,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 +486,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 +516,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 +552,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 +705,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 +834,7 @@ void ItemList::_notification(int p_what) { } if (shape_changed) { - + float max_column_width = 0; //1- compute item minimum sizes @@ -914,11 +925,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 +1040,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 +1068,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 +1109,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 +1129,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); } @@ -1191,6 +1210,9 @@ String ItemList::get_tooltip(const Point2& p_pos) const { int closest = get_item_at_pos(p_pos); if (closest!=-1) { + if (!items[closest].tooltip_enabled) { + return ""; + } if (items[closest].tooltip!="") { return items[closest].tooltip; } @@ -1203,8 +1225,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) { @@ -1284,6 +1309,9 @@ void ItemList::_bind_methods(){ ObjectTypeDB::bind_method(_MD("set_item_custom_bg_color","idx","custom_bg_color"),&ItemList::set_item_custom_bg_color); ObjectTypeDB::bind_method(_MD("get_item_custom_bg_color","idx"),&ItemList::get_item_custom_bg_color); + ObjectTypeDB::bind_method(_MD("set_item_tooltip_enabled","idx","enable"),&ItemList::set_item_tooltip_enabled); + ObjectTypeDB::bind_method(_MD("is_item_tooltip_enabled","idx"),&ItemList::is_item_tooltip_enabled); + ObjectTypeDB::bind_method(_MD("set_item_tooltip","idx","tooltip"),&ItemList::set_item_tooltip); ObjectTypeDB::bind_method(_MD("get_item_tooltip","idx"),&ItemList::get_item_tooltip); @@ -1296,7 +1324,7 @@ void ItemList::_bind_methods(){ 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,6 +1358,8 @@ void ItemList::_bind_methods(){ ObjectTypeDB::bind_method(_MD("ensure_current_is_visible"),&ItemList::ensure_current_is_visible); + ObjectTypeDB::bind_method(_MD("get_v_scroll"),&ItemList::get_v_scroll); + ObjectTypeDB::bind_method(_MD("_scroll_changed"),&ItemList::_scroll_changed); ObjectTypeDB::bind_method(_MD("_input_event"),&ItemList::_input_event); @@ -1375,4 +1405,3 @@ ItemList::ItemList() { ItemList::~ItemList() { } - diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h index e1902d1c1f..cb5908bc79 100644 --- a/scene/gui/item_list.h +++ b/scene/gui/item_list.h @@ -56,6 +56,7 @@ private: bool selectable; bool selected; bool disabled; + bool tooltip_enabled; Variant metadata; String tooltip; Color custom_bg; @@ -135,6 +136,9 @@ public: void set_item_tag_icon(int p_idx,const Ref<Texture>& p_tag_icon); Ref<Texture> get_item_tag_icon(int p_idx) const; + void set_item_tooltip_enabled(int p_idx, const bool p_enabled); + bool is_item_tooltip_enabled(int p_idx) const; + void set_item_tooltip(int p_idx,const String& p_tooltip); String get_item_tooltip(int p_idx) const; @@ -191,6 +195,8 @@ public: void set_icon_scale(real_t p_scale); real_t get_icon_scale() const; + VScrollBar *get_v_scroll() { return scroll_bar; } + ItemList(); ~ItemList(); }; diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index 0431d824fa..ec89b7b690 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -334,7 +334,7 @@ int Label::get_longest_line_width() const { } } else { - int char_width=font->get_char_size(current).width; + int char_width=font->get_char_size(current,text[i+1]).width; line_width+=char_width; } @@ -356,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) { @@ -439,7 +454,7 @@ void Label::regenerate_word_cache() { word_pos=i; } - char_width=font->get_char_size(current).width; + char_width=font->get_char_size(current,text[i+1]).width; current_word_size+=char_width; line_width+=char_width; total_char_cache++; @@ -640,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 6c47072b33..90a8af9238 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -118,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); @@ -193,8 +193,8 @@ void LineEdit::_input_event(InputEvent p_event) { } set_cursor_pos(0); - emit_signal("text_changed",text); - _change_notify("text"); + _text_changed(); + } @@ -215,8 +215,7 @@ void LineEdit::_input_event(InputEvent p_event) { selection_clear(); undo_text = text; text = text.substr(0,cursor_pos); - emit_signal("text_changed",text); - _change_notify("text"); + _text_changed(); } } break; @@ -468,16 +467,14 @@ void LineEdit::_input_event(InputEvent p_event) { if (handled) { accept_event(); - } else { + } else if (!k.mod.alt && !k.mod.command) { if (k.unicode>=32 && k.scancode!=KEY_DELETE) { if (editable) { selection_delete(); CharType ucodestr[2]={(CharType)k.unicode,0}; append_at_cursor(ucodestr); - emit_signal("text_changed",text); - _change_notify("text"); - + _text_changed(); accept_event(); } @@ -616,11 +613,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; } @@ -725,8 +722,7 @@ void LineEdit::paste_text() { if(selection.enabled) selection_delete(); append_at_cursor(paste_buffer); - emit_signal("text_changed",text); - _change_notify("text"); + _text_changed(); } @@ -750,9 +746,7 @@ void LineEdit::undo() { set_cursor_pos(old_cursor_pos); } - emit_signal("text_changed",text); - _change_notify("text"); - + _text_changed(); } void LineEdit::shift_selection_check_pre(bool p_shift) { @@ -806,13 +800,6 @@ void LineEdit::set_cursor_at_pixel_pos(int p_x) { pixel_ofs+=char_w; if (pixel_ofs > p_x) { //found what we look for - - - if ( (pixel_ofs-p_x) < (char_w >> 1 ) ) { - - ofs+=1; - } - break; } @@ -888,8 +875,7 @@ void LineEdit::delete_char() { // set_window_pos(cursor_pos-get_window_length()); } - emit_signal("text_changed",text); - _change_notify("text"); + _text_changed(); } void LineEdit::delete_text(int p_from_column, int p_to_column) { @@ -921,8 +907,7 @@ void LineEdit::delete_text(int p_from_column, int p_to_column) { window_pos=cursor_pos; } - emit_signal("text_changed",text); - _change_notify("text"); + _text_changed(); } void LineEdit::set_text(String p_text) { @@ -937,8 +922,7 @@ void LineEdit::set_text(String p_text) { void LineEdit::clear() { clear_internal(); - emit_signal("text_changed",text); - _change_notify("text"); + _text_changed(); } String LineEdit::get_text() const { @@ -1077,7 +1061,17 @@ Size2 LineEdit::get_minimum_size() const { Size2 min=style->get_minimum_size(); min.height+=font->get_height(); - min.width+=get_constant("minimum_spaces")*font->get_char_size(' ').x; + + //minimum size of text + int space_size = font->get_char_size(' ').x; + int mstext = get_constant("minimum_spaces")*space_size; + + if (expand_to_text_length) { + mstext=MAX(mstext,font->get_string_size(text).x+space_size); //add a spce because some fonts are too exact + } + + min.width+=mstext; + return min; } @@ -1233,6 +1227,29 @@ PopupMenu *LineEdit::get_menu() const { } #endif + +void LineEdit::set_expand_to_text_length(bool p_enabled) { + + expand_to_text_length = p_enabled; + minimum_size_changed(); +} + +bool LineEdit::get_expand_to_text_length() const{ + + return expand_to_text_length; +} + + +void LineEdit::_text_changed() { + + if (expand_to_text_length) + minimum_size_changed(); + + emit_signal("text_changed",text); + _change_notify("text"); + +} + void LineEdit::_bind_methods() { ObjectTypeDB::bind_method(_MD("_toggle_draw_caret"),&LineEdit::_toggle_draw_caret); @@ -1255,7 +1272,9 @@ void LineEdit::_bind_methods() { 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); + ObjectTypeDB::bind_method(_MD("set_expand_to_text_length","enabled"),&LineEdit::set_expand_to_text_length); + ObjectTypeDB::bind_method(_MD("get_expand_to_text_length"),&LineEdit::get_expand_to_text_length); + ObjectTypeDB::bind_method(_MD("cursor_set_blink_enabled", "enabled"),&LineEdit::cursor_set_blink_enabled); ObjectTypeDB::bind_method(_MD("cursor_get_blink_enabled"),&LineEdit::cursor_get_blink_enabled); ObjectTypeDB::bind_method(_MD("cursor_set_blink_speed", "blink_speed"),&LineEdit::cursor_set_blink_speed); ObjectTypeDB::bind_method(_MD("cursor_get_blink_speed"),&LineEdit::cursor_get_blink_speed); @@ -1293,6 +1312,7 @@ void LineEdit::_bind_methods() { 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") ); ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "secret" ), _SCS("set_secret"),_SCS("is_secret") ); + ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "expand_to_len" ), _SCS("set_expand_to_text_length"),_SCS("get_expand_to_text_length") ); ADD_PROPERTY( PropertyInfo( Variant::INT,"focus_mode", PROPERTY_HINT_ENUM, "None,Click,All" ), _SCS("set_focus_mode"), _SCS("get_focus_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") ); @@ -1334,7 +1354,7 @@ LineEdit::LineEdit() { menu->add_separator(); menu->add_item(TTR("Undo"),MENU_UNDO,KEY_MASK_CMD|KEY_Z); menu->connect("item_pressed",this,"menu_option"); - + expand_to_text_length=false; } diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 112e4ad55e..47d5706bbe 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -90,6 +90,11 @@ private: } selection; Timer *caret_blink_timer; + + + void _text_changed(); + bool expand_to_text_length; + bool caret_blink_enabled; bool draw_caret; bool window_has_focus; @@ -169,6 +174,9 @@ public: virtual Size2 get_minimum_size() const; + void set_expand_to_text_length(bool p_len); + bool get_expand_to_text_length() const; + virtual bool is_text_field() const; LineEdit(); ~LineEdit(); 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/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index b4fa463cde..73a3cda5f3 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -662,7 +662,9 @@ void RichTextLabel::_notification(int p_what) { } break; case NOTIFICATION_ENTER_TREE: { - set_bbcode(bbcode); + if (bbcode != "") + set_bbcode(bbcode); + main->first_invalid_line=0; //invalidate ALL update(); diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index 190e8e141f..0fa2856ca4 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -228,14 +228,14 @@ void ScrollContainer::_notification(int p_what) { child_max_size.y = MAX(child_max_size.y, minsize.y); Rect2 r = Rect2(-scroll,minsize); - if (!scroll_h) { + if (!h_scroll->is_visible()) { r.pos.x=0; if (c->get_h_size_flags()&SIZE_EXPAND) r.size.width=MAX(size.width,minsize.width); else r.size.width=minsize.width; } - if (!scroll_v) { + if (!v_scroll->is_visible()) { r.pos.y=0; r.size.height=size.height; if (c->get_v_size_flags()&SIZE_EXPAND) diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp index d5d14ad649..3b9ca40bd8 100644 --- a/scene/gui/slider.cpp +++ b/scene/gui/slider.cpp @@ -47,12 +47,15 @@ void Slider::_input_event(InputEvent p_event) { if (mb.button_index==BUTTON_LEFT) { if (mb.pressed) { + Ref<Texture> grabber = get_icon(mouse_inside||has_focus()?"grabber_hilite":"grabber"); grab.pos=orientation==VERTICAL?mb.y:mb.x; - double max = orientation==VERTICAL ? get_size().height : get_size().width ; + double grab_width = (double)grabber->get_size().width; + double grab_height = (double)grabber->get_size().height; + double max = orientation==VERTICAL ? get_size().height - grab_height : get_size().width - grab_width; if (orientation==VERTICAL) - set_unit_value( 1 - ((double)grab.pos / max) ); + set_unit_value( 1 - (((double)grab.pos - (grab_height / 2.0)) / max) ); else - set_unit_value((double)grab.pos / max); + set_unit_value(((double)grab.pos - (grab_width/2.0)) / max); grab.active=true; grab.uvalue=get_unit_value(); } else { diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index 2b64d36a81..98e1a32aef 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -39,7 +39,7 @@ Size2 SpinBox::get_minimum_size() const { void SpinBox::_value_changed(double) { - String value = String::num(get_val(),Math::decimals(get_step())); + String value = String::num(get_val(),Math::step_decimals(get_step())); if (prefix!="") value=prefix+" "+value; if (suffix!="") diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 0e0339c488..8557500488 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -400,6 +400,7 @@ void TabContainer::_child_renamed_callback() { void TabContainer::add_child_notify(Node *p_child) { + Control::add_child_notify(p_child); Control *c = p_child->cast_to<Control>(); if (!c) @@ -532,6 +533,8 @@ Control* TabContainer::get_current_tab_control() const { void TabContainer::remove_child_notify(Node *p_child) { + Control::remove_child_notify(p_child); + int tc = get_tab_count(); if (current==tc-1) { current--; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index a680d5d873..4756fdee26 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -999,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) { @@ -1034,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); } } } @@ -1502,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; } } @@ -1759,7 +1768,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { return; } - if (k.scancode==KEY_RETURN || k.scancode==KEY_TAB) { + if (k.scancode==KEY_ENTER || k.scancode==KEY_RETURN || k.scancode==KEY_TAB) { _confirm_completion(); accept_event(); @@ -2984,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) @@ -3074,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) { @@ -3315,6 +3361,7 @@ void TextEdit::_update_caches() { 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"); @@ -4417,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); @@ -4459,15 +4508,18 @@ 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, "syntax_highlighting"), _SCS("set_syntax_coloring"), _SCS("is_syntax_coloring_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 ); @@ -4527,6 +4579,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); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 270a1723b1..f0301fc250 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -79,6 +79,7 @@ class TextEdit : public Control { 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; @@ -222,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; @@ -394,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); @@ -406,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); @@ -431,7 +438,7 @@ public: bool is_highlight_all_occurrences_enabled() const; bool is_selection_active() const; int get_selection_from_line() const; - int get_selection_from_column() const; + int get_selection_from_column() const; int get_selection_to_line() const; int get_selection_to_column() const; String get_selection_text() const; @@ -489,7 +496,7 @@ public: String get_text_for_completion(); - virtual bool is_text_field() const; + virtual bool is_text_field() const; TextEdit(); ~TextEdit(); }; diff --git a/scene/gui/texture_progress.cpp b/scene/gui/texture_progress.cpp index 923a35031c..2c576b6ba5 100644 --- a/scene/gui/texture_progress.cpp +++ b/scene/gui/texture_progress.cpp @@ -297,6 +297,7 @@ void TextureProgress::_bind_methods() { TextureProgress::TextureProgress() { mode=FILL_LEFT_TO_RIGHT; + rad_init_angle=0; rad_center_off=Point2(); rad_max_degrees=360; } diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 305a3920da..20794b2faa 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -171,6 +171,21 @@ String TreeItem::get_text(int p_column) const { } +void TreeItem::set_suffix(int p_column,String p_suffix) { + + ERR_FAIL_INDEX( p_column, cells.size() ); + cells[p_column].suffix=p_suffix; + + _changed_notify(p_column); + +} + +String TreeItem::get_suffix(int p_column) const { + + ERR_FAIL_INDEX_V( p_column, cells.size(), "" ); + return cells[p_column].suffix; + +} void TreeItem::set_icon(int p_column,const Ref<Texture>& p_icon) { @@ -693,6 +708,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); @@ -926,8 +942,12 @@ void Tree::draw_item_rect(const TreeItem::Cell& p_cell,const Rect2i& p_rect,cons Ref<Font> font = cache.font; + String text = p_cell.text; + if (p_cell.suffix!=String()) + text+=" "+p_cell.suffix; + rect.pos.y+=Math::floor((rect.size.y-font->get_height())/2.0) +font->get_ascent(); - font->draw(ci,rect.pos,p_cell.text,p_color,rect.size.x); + font->draw(ci,rect.pos,text,p_color,rect.size.x); } @@ -1071,11 +1091,21 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2& if (p_item->cells[i].selected && select_mode!=SELECT_ROW) { Rect2i r(item_rect.pos,item_rect.size); + if (p_item->cells[i].text.size() > 0){ + float icon_width = p_item->cells[i].get_icon_size().width; + r.pos.x += icon_width; + r.size.x -= icon_width; + } //r.grow(cache.selected->get_margin(MARGIN_LEFT)); - if (has_focus()) + if (has_focus()){ cache.selected_focus->draw(ci,r ); - else + p_item->set_meta("__focus_rect", Rect2(r.pos,r.size)); + } else { cache.selected->draw(ci,r ); + } + if (text_editor->is_visible()){ + text_editor->set_pos(get_global_pos() + r.pos); + } } if (p_item->cells[i].custom_bg_color) { @@ -1164,6 +1194,9 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2& String s = p_item->cells[i].text; s=s.get_slicec(',',option); + if (p_item->cells[i].suffix!=String()) + s+=" "+p_item->cells[i].suffix; + Ref<Texture> downarrow = cache.select_arrow; font->draw(ci, text_pos, s, col,item_rect.size.x-downarrow->get_width() ); @@ -1178,8 +1211,12 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2& Ref<Texture> updown = cache.updown; - //String valtext = String::num( p_item->cells[i].val, Math::decimals( p_item->cells[i].step ) ); - String valtext = rtos( p_item->cells[i].val ); + String valtext = String::num( p_item->cells[i].val, Math::step_decimals( p_item->cells[i].step ) ); + //String valtext = rtos( p_item->cells[i].val ); + + if (p_item->cells[i].suffix!=String()) + valtext+=" "+p_item->cells[i].suffix; + font->draw( ci, text_pos, valtext, col, item_rect.size.x-updown->get_width()); if (!p_item->cells[i].editable) @@ -1745,7 +1782,7 @@ 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 ) ); + editor_text=String::num( p_item->cells[col].val, Math::step_decimals( p_item->cells[col].step ) ); if (select_mode==SELECT_MULTI && get_tree()->get_last_event_id() == focus_in_id) bring_up_editor=false; @@ -2327,9 +2364,22 @@ void Tree::_input_event(InputEvent p_event) { range_drag_enabled=false; Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); warp_mouse(range_drag_capture_pos); - } else - edit_selected(); + } else { + if (delayed_text_editor) { + uint64_t diff = OS::get_singleton()->get_ticks_msec() - first_selection_time; + if (diff >= 400 && diff <= 800) + edit_selected(); + // fast double click + else if (diff < 400) { + emit_signal("item_double_clicked"); + } + + first_selection_time = OS::get_singleton()->get_ticks_msec(); + } else { + edit_selected(); + } + } pressing_for_editor=false; } @@ -2467,16 +2517,7 @@ bool Tree::edit_selected() { if (!s->cells[col].editable) return false; - Rect2 rect; - rect.pos.y = get_item_offset(s) - get_scroll().y; - - for(int i=0;i<col;i++) { - - rect.pos.x+=get_column_width(i); - } - - rect.size.width=get_column_width(col); - rect.size.height=compute_item_height(s)+cache.vseparation; + Rect2 rect = s->get_meta("__focus_rect"); popup_edited_item=s; popup_edited_item_col=col; @@ -2520,7 +2561,7 @@ bool Tree::edit_selected() { text_editor->set_pos( textedpos ); text_editor->set_size( rect.size); text_editor->clear(); - text_editor->set_text( c.mode==TreeItem::CELL_MODE_STRING?c.text:rtos(c.val) ); + text_editor->set_text( c.mode==TreeItem::CELL_MODE_STRING?c.text:String::num( c.val, Math::step_decimals( c.step ) ) ); text_editor->select_all(); if (c.mode==TreeItem::CELL_MODE_RANGE || c.mode==TreeItem::CELL_MODE_RANGE_EXPRESSION ) { @@ -2847,7 +2888,6 @@ void Tree::item_changed(int p_column,TreeItem *p_item) { void Tree::item_selected(int p_column,TreeItem *p_item) { - if (select_mode==SELECT_MULTI) { if (!p_item->cells[p_column].selectable) @@ -2855,8 +2895,11 @@ void Tree::item_selected(int p_column,TreeItem *p_item) { p_item->cells[p_column].selected=true; //emit_signal("multi_selected",p_item,p_column,true); - NO this is for TreeItem::select + if (delayed_text_editor) + first_selection_time = OS::get_singleton()->get_ticks_msec(); } else { + select_single_item(p_item,root,p_column); } update(); @@ -3127,7 +3170,7 @@ void Tree::ensure_cursor_is_visible() { int screenh=get_size().height-h_scroll->get_combined_minimum_size().height; if (ofs+h>v_scroll->get_val()+screenh) - v_scroll->set_val(ofs-screenh+h); + v_scroll->call_deferred("set_val", ofs-screenh+h); else if (ofs < v_scroll->get_val()) v_scroll->set_val(ofs); } @@ -3502,6 +3545,16 @@ bool Tree::get_allow_rmb_select() const{ return allow_rmb_select; } + +void Tree::set_delayed_text_editor(bool enabled) { + delayed_text_editor = enabled; +} + +bool Tree::is_delayed_text_editor_enabled() const { + return delayed_text_editor; +} + + void Tree::_bind_methods() { ObjectTypeDB::bind_method(_MD("_range_click_timeout"),&Tree::_range_click_timeout); @@ -3555,6 +3608,9 @@ void Tree::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_allow_rmb_select","allow"),&Tree::set_allow_rmb_select); ObjectTypeDB::bind_method(_MD("get_allow_rmb_select"),&Tree::get_allow_rmb_select); + ObjectTypeDB::bind_method(_MD("set_delayed_text_editor","enable"),&Tree::set_delayed_text_editor); + ObjectTypeDB::bind_method(_MD("is_delayed_text_editor_enabled"),&Tree::is_delayed_text_editor_enabled); + ObjectTypeDB::bind_method(_MD("set_single_select_cell_editing_only_when_already_selected","enable"),&Tree::set_single_select_cell_editing_only_when_already_selected); ObjectTypeDB::bind_method(_MD("get_single_select_cell_editing_only_when_already_selected"),&Tree::get_single_select_cell_editing_only_when_already_selected); @@ -3565,6 +3621,7 @@ void Tree::_bind_methods() { ADD_SIGNAL( MethodInfo("item_rmb_selected",PropertyInfo(Variant::VECTOR2,"pos"))); ADD_SIGNAL( MethodInfo("empty_tree_rmb_selected",PropertyInfo(Variant::VECTOR2,"pos"))); ADD_SIGNAL( MethodInfo("item_edited")); + ADD_SIGNAL( MethodInfo("item_double_clicked")); ADD_SIGNAL( MethodInfo("item_collapsed",PropertyInfo(Variant::OBJECT,"item"))); //ADD_SIGNAL( MethodInfo("item_doubleclicked" ) ); ADD_SIGNAL( MethodInfo("button_pressed",PropertyInfo(Variant::OBJECT,"item"),PropertyInfo(Variant::INT,"column"),PropertyInfo(Variant::INT,"id"))); @@ -3668,6 +3725,9 @@ Tree::Tree() { force_select_on_already_selected=false; allow_rmb_select=false; + + first_selection_time = 0; + delayed_text_editor = false; } diff --git a/scene/gui/tree.h b/scene/gui/tree.h index f5100ab5b6..2124dce749 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -69,6 +69,7 @@ friend class Tree; Ref<Texture> icon; Rect2i icon_region; String text; + String suffix; double min,max,step,val; int icon_max_w; bool expr; @@ -168,6 +169,9 @@ public: void set_text(int p_column,String p_text); String get_text(int p_column) const; + void set_suffix(int p_column,String p_suffix); + String get_suffix(int p_column) const; + void set_icon(int p_column,const Ref<Texture>& p_icon); Ref<Texture> get_icon(int p_column) const; @@ -433,6 +437,9 @@ friend class TreeItem; float last_drag_time; float time_since_motion;*/ + bool delayed_text_editor; + uint64_t first_selection_time; + float drag_speed; float drag_from; float drag_accum; @@ -527,6 +534,9 @@ public: void set_value_evaluator(ValueEvaluator *p_evaluator); + void set_delayed_text_editor(bool enabled); + bool is_delayed_text_editor_enabled() const; + Tree(); ~Tree(); diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index 040d509286..c713b5e4dc 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -96,7 +96,7 @@ Error HTTPRequest::_parse_url(const String& p_url) { return OK; } -Error HTTPRequest::request(const String& p_url, const Vector<String>& p_custom_headers, bool p_ssl_validate_domain) { +Error HTTPRequest::request(const String& p_url, const Vector<String>& p_custom_headers, bool p_ssl_validate_domain, HTTPClient::Method p_method, const String& p_request_data) { ERR_FAIL_COND_V(!is_inside_tree(),ERR_UNCONFIGURED); if ( requesting ) { @@ -104,13 +104,20 @@ Error HTTPRequest::request(const String& p_url, const Vector<String>& p_custom_h ERR_FAIL_V(ERR_BUSY); } + method=p_method; + Error err = _parse_url(p_url); + if (err) + return err; + validate_ssl=p_ssl_validate_domain; bool has_user_agent=false; bool has_accept=false; headers=p_custom_headers; + request_data = p_request_data; + for(int i=0;i<headers.size();i++) { if (headers[i].findn("user-agent:")==0) @@ -127,19 +134,52 @@ Error HTTPRequest::request(const String& p_url, const Vector<String>& p_custom_h headers.push_back("Accept: */*"); } + requesting=true; + + if (use_threads) { - err = _request(); + thread_done=false; + thread_request_quit=false; + client->set_blocking_mode(true); + thread=Thread::create(_thread_func,this); + } else { + client->set_blocking_mode(false); + err = _request(); + if (err!=OK) { + call_deferred("_request_done",RESULT_CANT_CONNECT,0,StringArray(),ByteArray()); + return ERR_CANT_CONNECT; + } - if (err==OK) { set_process(true); - requesting=true; + } - return err; + return OK; } +void HTTPRequest::_thread_func(void *p_userdata) { + + HTTPRequest *hr = (HTTPRequest*)p_userdata; + + Error err = hr->_request(); + + if (err!=OK) { + hr->call_deferred("_request_done",RESULT_CANT_CONNECT,0,StringArray(),ByteArray()); + } else { + while(!hr->thread_request_quit) { + + bool exit = hr->_update_connection(); + if (exit) + break; + OS::get_singleton()->delay_usec(1); + } + } + + hr->thread_done=true; +} + void HTTPRequest::cancel_request() { if (!requesting) @@ -147,6 +187,11 @@ void HTTPRequest::cancel_request() { if (!use_threads) { set_process(false); + } else { + thread_request_quit=true; + Thread::wait_to_finish(thread); + memdelete(thread); + thread=NULL; } if (file) { @@ -167,7 +212,7 @@ void HTTPRequest::cancel_request() { bool HTTPRequest::_handle_response(bool *ret_value) { if (!client->has_response()) { - call_deferred("emit_signal","request_completed",RESULT_NO_RESPONSE,0,StringArray(),ByteArray()); + call_deferred("_request_done",RESULT_NO_RESPONSE,0,StringArray(),ByteArray()); *ret_value=true; return true; } @@ -187,7 +232,7 @@ bool HTTPRequest::_handle_response(bool *ret_value) { //redirect if (max_redirects>=0 && redirections>=max_redirects) { - call_deferred("emit_signal","request_completed",RESULT_REDIRECT_LIMIT_REACHED,response_code,response_headers,ByteArray()); + call_deferred("_request_done",RESULT_REDIRECT_LIMIT_REACHED,response_code,response_headers,ByteArray()); *ret_value=true; return true; } @@ -239,6 +284,7 @@ bool HTTPRequest::_update_connection() { switch( client->get_status() ) { case HTTPClient::STATUS_DISCONNECTED: { + call_deferred("_request_done",RESULT_CANT_CONNECT,0,StringArray(),ByteArray()); return true; //end it, since it's doing something } break; case HTTPClient::STATUS_RESOLVING: { @@ -247,7 +293,7 @@ bool HTTPRequest::_update_connection() { return false; } break; case HTTPClient::STATUS_CANT_RESOLVE: { - call_deferred("emit_signal","request_completed",RESULT_CANT_RESOLVE,0,StringArray(),ByteArray()); + call_deferred("_request_done",RESULT_CANT_RESOLVE,0,StringArray(),ByteArray()); return true; } break; @@ -258,7 +304,7 @@ bool HTTPRequest::_update_connection() { } break; //connecting to ip case HTTPClient::STATUS_CANT_CONNECT: { - call_deferred("emit_signal","request_completed",RESULT_CANT_CONNECT,0,StringArray(),ByteArray()); + call_deferred("_request_done",RESULT_CANT_CONNECT,0,StringArray(),ByteArray()); return true; } break; @@ -276,25 +322,25 @@ bool HTTPRequest::_update_connection() { return ret_value; - call_deferred("emit_signal","request_completed",RESULT_SUCCESS,response_code,response_headers,ByteArray()); + call_deferred("_request_done",RESULT_SUCCESS,response_code,response_headers,ByteArray()); return true; } if (got_response && body_len<0) { //chunked transfer is done - call_deferred("emit_signal","request_completed",RESULT_SUCCESS,response_code,response_headers,body); + call_deferred("_request_done",RESULT_SUCCESS,response_code,response_headers,body); return true; } - call_deferred("emit_signal","request_completed",RESULT_CHUNKED_BODY_SIZE_MISMATCH,response_code,response_headers,ByteArray()); + call_deferred("_request_done",RESULT_CHUNKED_BODY_SIZE_MISMATCH,response_code,response_headers,ByteArray()); return true; //request migh have been done } else { //did not request yet, do request - Error err = client->request(HTTPClient::METHOD_GET,request_string,headers); + Error err = client->request(method,request_string,headers,request_data); if (err!=OK) { - call_deferred("emit_signal","request_completed",RESULT_CONNECTION_ERROR,0,StringArray(),ByteArray()); + call_deferred("_request_done",RESULT_CONNECTION_ERROR,0,StringArray(),ByteArray()); return true; } @@ -320,7 +366,7 @@ bool HTTPRequest::_update_connection() { if (!client->is_response_chunked() && client->get_response_body_length()==0) { - call_deferred("emit_signal","request_completed",RESULT_SUCCESS,response_code,response_headers,ByteArray()); + call_deferred("_request_done",RESULT_SUCCESS,response_code,response_headers,ByteArray()); return true; } @@ -331,7 +377,7 @@ bool HTTPRequest::_update_connection() { body_len=client->get_response_body_length(); if (body_size_limit>=0 && body_len>body_size_limit) { - call_deferred("emit_signal","request_completed",RESULT_BODY_SIZE_LIMIT_EXCEEDED,response_code,response_headers,ByteArray()); + call_deferred("_request_done",RESULT_BODY_SIZE_LIMIT_EXCEEDED,response_code,response_headers,ByteArray()); return true; } } @@ -340,7 +386,8 @@ bool HTTPRequest::_update_connection() { file=FileAccess::open(download_to_file,FileAccess::WRITE); if (!file) { - call_deferred("emit_signal","request_completed",RESULT_DOWNLOAD_FILE_CANT_OPEN,response_code,response_headers,ByteArray()); + call_deferred("_request_done",RESULT_DOWNLOAD_FILE_CANT_OPEN,response_code,response_headers,ByteArray()); + return true; } } } @@ -356,7 +403,7 @@ bool HTTPRequest::_update_connection() { ByteArray::Read r=chunk.read(); file->store_buffer(r.ptr(),chunk.size()); if (file->get_error()!=OK) { - call_deferred("emit_signal","request_completed",RESULT_DOWNLOAD_FILE_WRITE_ERROR,response_code,response_headers,ByteArray()); + call_deferred("_request_done",RESULT_DOWNLOAD_FILE_WRITE_ERROR,response_code,response_headers,ByteArray()); return true; } } else { @@ -364,18 +411,18 @@ bool HTTPRequest::_update_connection() { } if (body_size_limit>=0 && downloaded>body_size_limit) { - call_deferred("emit_signal","request_completed",RESULT_BODY_SIZE_LIMIT_EXCEEDED,response_code,response_headers,ByteArray()); + call_deferred("_request_done",RESULT_BODY_SIZE_LIMIT_EXCEEDED,response_code,response_headers,ByteArray()); return true; } if (body_len>=0) { if (downloaded==body_len) { - call_deferred("emit_signal","request_completed",RESULT_SUCCESS,response_code,response_headers,body); + call_deferred("_request_done",RESULT_SUCCESS,response_code,response_headers,body); return true; } /*if (body.size()>=body_len) { - call_deferred("emit_signal","request_completed",RESULT_BODY_SIZE_MISMATCH,response_code,response_headers,ByteArray()); + call_deferred("_request_done",RESULT_BODY_SIZE_MISMATCH,response_code,response_headers,ByteArray()); return true; }*/ } @@ -384,11 +431,11 @@ bool HTTPRequest::_update_connection() { } break; // request resulted in body: { } break which must be read case HTTPClient::STATUS_CONNECTION_ERROR: { - call_deferred("emit_signal","request_completed",RESULT_CONNECTION_ERROR,0,StringArray(),ByteArray()); + call_deferred("_request_done",RESULT_CONNECTION_ERROR,0,StringArray(),ByteArray()); return true; } break; case HTTPClient::STATUS_SSL_HANDSHAKE_ERROR: { - call_deferred("emit_signal","request_completed",RESULT_SSL_HANDSHAKE_ERROR,0,StringArray(),ByteArray()); + call_deferred("_request_done",RESULT_SSL_HANDSHAKE_ERROR,0,StringArray(),ByteArray()); return true; } break; @@ -397,17 +444,35 @@ bool HTTPRequest::_update_connection() { ERR_FAIL_V(false); } + +void HTTPRequest::_request_done(int p_status, int p_code, const StringArray& headers, const ByteArray& p_data) { + + + cancel_request(); + emit_signal("request_completed",p_status,p_code,headers,p_data); +} + + void HTTPRequest::_notification(int p_what) { if (p_what==NOTIFICATION_PROCESS) { + if (use_threads) + return; bool done = _update_connection(); if (done) { set_process(false); + //cancel_request(); called from _request done now + } + } + + if (p_what==NOTIFICATION_EXIT_TREE) { + if (requesting) { cancel_request(); } } + } void HTTPRequest::set_use_threads(bool p_use) { @@ -470,7 +535,7 @@ int HTTPRequest::get_body_size() const{ void HTTPRequest::_bind_methods() { - ObjectTypeDB::bind_method(_MD("request","url","custom_headers","ssl_validate_domain"),&HTTPRequest::request,DEFVAL(StringArray()),DEFVAL(true)); + ObjectTypeDB::bind_method(_MD("request","url","custom_headers","ssl_validate_domain","method","request_data"),&HTTPRequest::request,DEFVAL(StringArray()),DEFVAL(true),DEFVAL(HTTPClient::METHOD_GET),DEFVAL(String())); ObjectTypeDB::bind_method(_MD("cancel_request"),&HTTPRequest::cancel_request); ObjectTypeDB::bind_method(_MD("get_http_client_status"),&HTTPRequest::get_http_client_status); @@ -491,6 +556,7 @@ void HTTPRequest::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_body_size"),&HTTPRequest::get_body_size); ObjectTypeDB::bind_method(_MD("_redirect_request"),&HTTPRequest::_redirect_request); + ObjectTypeDB::bind_method(_MD("_request_done"),&HTTPRequest::_request_done); ADD_PROPERTY(PropertyInfo(Variant::BOOL,"use_threads"),_SCS("set_use_threads"),_SCS("is_using_threads")); ADD_PROPERTY(PropertyInfo(Variant::INT,"body_size_limit",PROPERTY_HINT_RANGE,"-1,2000000000"),_SCS("set_body_size_limit"),_SCS("get_body_size_limit")); @@ -517,6 +583,7 @@ void HTTPRequest::_bind_methods() { HTTPRequest::HTTPRequest() { + thread=NULL; port=80; redirections=0; @@ -530,6 +597,7 @@ HTTPRequest::HTTPRequest() requesting=false; client.instance(); use_threads=false; + thread_done=false; body_size_limit=-1; file=NULL; status=HTTPClient::STATUS_DISCONNECTED; diff --git a/scene/main/http_request.h b/scene/main/http_request.h index 7c3ccb2eb9..705799f044 100644 --- a/scene/main/http_request.h +++ b/scene/main/http_request.h @@ -32,6 +32,7 @@ #include "node.h" #include "io/http_client.h" #include "os/file_access.h" +#include "os/thread.h" class HTTPRequest : public Node { @@ -65,11 +66,13 @@ private: Vector<String> headers; bool validate_ssl; bool use_ssl; + HTTPClient::Method method; + String request_data; bool request_sent; Ref<HTTPClient> client; ByteArray body; - bool use_threads; + volatile bool use_threads; bool got_response; int response_code; @@ -80,7 +83,7 @@ private: FileAccess *file; int body_len; - int downloaded; + volatile int downloaded; int body_size_limit; int redirections; @@ -93,11 +96,19 @@ private: void _redirect_request(const String& p_new_url); + bool _handle_response(bool *ret_value); Error _parse_url(const String& p_url); Error _request(); + volatile bool thread_done; + volatile bool thread_request_quit; + + Thread *thread; + + void _request_done(int p_status, int p_code, const StringArray& headers, const ByteArray& p_data); + static void _thread_func(void *p_userdata); protected: @@ -105,7 +116,7 @@ protected: static void _bind_methods(); public: - Error request(const String& p_url,const Vector<String>& p_custom_headers=Vector<String>(),bool p_ssl_validate_domain=true); //connects to a full url and perform request + Error request(const String& p_url, const Vector<String>& p_custom_headers=Vector<String>(), bool p_ssl_validate_domain=true, HTTPClient::Method p_method=HTTPClient::METHOD_GET, const String& p_request_data=""); //connects to a full url and perform request void cancel_request(); HTTPClient::Status get_http_client_status() const; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 55106f5ee7..1892240426 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -36,6 +36,8 @@ #include "instance_placeholder.h" VARIANT_ENUM_CAST(Node::PauseMode); +VARIANT_ENUM_CAST(Node::NetworkMode); +VARIANT_ENUM_CAST(Node::RPCMode); @@ -77,6 +79,16 @@ void Node::_notification(int p_notification) { data.pause_owner=this; } + if (data.network_mode==NETWORK_MODE_INHERIT) { + + if (data.parent) + data.network_owner=data.parent->data.network_owner; + else + data.network_owner=NULL; + } else { + data.network_owner=this; + } + if (data.input) add_to_group("_vp_input"+itos(get_viewport()->get_instance_ID())); if (data.unhandled_input) @@ -97,6 +109,20 @@ void Node::_notification(int p_notification) { if (data.unhandled_key_input) remove_from_group("_vp_unhandled_key_input"+itos(get_viewport()->get_instance_ID())); + + data.pause_owner=NULL; + data.network_owner=NULL; + if (data.path_cache) { + memdelete(data.path_cache); + data.path_cache=NULL; + } + } break; + case NOTIFICATION_PATH_CHANGED: { + + if (data.path_cache) { + memdelete(data.path_cache); + data.path_cache=NULL; + } } break; case NOTIFICATION_READY: { @@ -412,6 +438,640 @@ void Node::_propagate_pause_owner(Node*p_owner) { } } +void Node::set_network_mode(NetworkMode p_mode) { + + if (data.network_mode==p_mode) + return; + + bool prev_inherits=data.network_mode==NETWORK_MODE_INHERIT; + data.network_mode=p_mode; + if (!is_inside_tree()) + return; //pointless + if ((data.network_mode==NETWORK_MODE_INHERIT) == prev_inherits) + return; ///nothing changed + + Node *owner=NULL; + + if (data.network_mode==NETWORK_MODE_INHERIT) { + + if (data.parent) + owner=data.parent->data.network_owner; + } else { + owner=this; + } + + _propagate_network_owner(owner); + + + +} + +Node::NetworkMode Node::get_network_mode() const { + + return data.network_mode; +} + +bool Node::is_network_master() const { + + ERR_FAIL_COND_V(!is_inside_tree(),false); + + switch(data.network_mode) { + case NETWORK_MODE_INHERIT: { + + if (data.network_owner) + return data.network_owner->is_network_master(); + else + return get_tree()->is_network_server(); + } break; + case NETWORK_MODE_MASTER: { + + return true; + } break; + case NETWORK_MODE_SLAVE: { + return false; + } break; + } + + return false; +} + + + +void Node::_propagate_network_owner(Node*p_owner) { + + if (data.network_mode!=NETWORK_MODE_INHERIT) + return; + data.network_owner=p_owner; + for(int i=0;i<data.children.size();i++) { + + data.children[i]->_propagate_network_owner(p_owner); + } +} + +/***** RPC CONFIG ********/ + +void Node::rpc_config(const StringName& p_method,RPCMode p_mode) { + + if (p_mode==RPC_MODE_DISABLED) { + data.rpc_methods.erase(p_method); + } else { + data.rpc_methods[p_method]=p_mode; + }; +} + +void Node::rset_config(const StringName& p_property,RPCMode p_mode) { + + if (p_mode==RPC_MODE_DISABLED) { + data.rpc_properties.erase(p_property); + } else { + data.rpc_properties[p_property]=p_mode; + }; +} + +/***** RPC FUNCTIONS ********/ + +void Node::rpc(const StringName& p_method,VARIANT_ARG_DECLARE) { + + VARIANT_ARGPTRS; + + int argc=0; + for(int i=0;i<VARIANT_ARG_MAX;i++) { + if (argptr[i]->get_type()==Variant::NIL) + break; + argc++; + } + + rpcp(0,false,p_method,argptr,argc); +} + + +void Node::rpc_id(int p_peer_id,const StringName& p_method,VARIANT_ARG_DECLARE) { + + VARIANT_ARGPTRS; + + int argc=0; + for(int i=0;i<VARIANT_ARG_MAX;i++) { + if (argptr[i]->get_type()==Variant::NIL) + break; + argc++; + } + + rpcp(p_peer_id,false,p_method,argptr,argc); +} + + +void Node::rpc_unreliable(const StringName& p_method,VARIANT_ARG_DECLARE) { + + VARIANT_ARGPTRS; + + int argc=0; + for(int i=0;i<VARIANT_ARG_MAX;i++) { + if (argptr[i]->get_type()==Variant::NIL) + break; + argc++; + } + + rpcp(0,true,p_method,argptr,argc); +} + + +void Node::rpc_unreliable_id(int p_peer_id,const StringName& p_method,VARIANT_ARG_DECLARE) { + + VARIANT_ARGPTRS; + + int argc=0; + for(int i=0;i<VARIANT_ARG_MAX;i++) { + if (argptr[i]->get_type()==Variant::NIL) + break; + argc++; + } + + rpcp(p_peer_id,true,p_method,argptr,argc); +} + + +Variant Node::_rpc_bind(const Variant** p_args, int p_argcount, Variant::CallError& r_error) { + + if (p_argcount<1) { + r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument=1; + return Variant(); + } + + if (p_args[0]->get_type()!=Variant::STRING) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_error.expected=Variant::STRING; + return Variant(); + } + + StringName method = *p_args[0]; + + rpcp(0,false,method,&p_args[1],p_argcount-1); + + r_error.error=Variant::CallError::CALL_OK; + return Variant(); +} + + +Variant Node::_rpc_id_bind(const Variant** p_args, int p_argcount, Variant::CallError& r_error) { + + if (p_argcount<2) { + r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument=2; + return Variant(); + } + + if (p_args[0]->get_type()!=Variant::INT) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_error.expected=Variant::INT; + return Variant(); + } + + if (p_args[1]->get_type()!=Variant::STRING) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=1; + r_error.expected=Variant::STRING; + return Variant(); + } + + int peer_id = *p_args[0]; + StringName method = *p_args[1]; + + rpcp(peer_id,false,method,&p_args[2],p_argcount-2); + + r_error.error=Variant::CallError::CALL_OK; + return Variant(); +} + + +Variant Node::_rpc_unreliable_bind(const Variant** p_args, int p_argcount, Variant::CallError& r_error) { + + if (p_argcount<1) { + r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument=1; + return Variant(); + } + + if (p_args[0]->get_type()!=Variant::STRING) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_error.expected=Variant::STRING; + return Variant(); + } + + StringName method = *p_args[0]; + + rpcp(0,true,method,&p_args[1],p_argcount-1); + + r_error.error=Variant::CallError::CALL_OK; + return Variant(); +} + + +Variant Node::_rpc_unreliable_id_bind(const Variant** p_args, int p_argcount, Variant::CallError& r_error) { + + if (p_argcount<2) { + r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument=2; + return Variant(); + } + + if (p_args[0]->get_type()!=Variant::INT) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_error.expected=Variant::INT; + return Variant(); + } + + if (p_args[1]->get_type()!=Variant::STRING) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=1; + r_error.expected=Variant::STRING; + return Variant(); + } + + int peer_id = *p_args[0]; + StringName method = *p_args[1]; + + rpcp(peer_id,true,method,&p_args[2],p_argcount-2); + + r_error.error=Variant::CallError::CALL_OK; + return Variant(); +} + +#if 0 +Variant Node::_rpc_bind(const Variant** p_args, int p_argcount, Variant::CallError& r_error) { + + if (p_argcount<1) { + r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument=1; + return Variant(); + } + + if (p_args[0]->get_type()!=Variant::STRING) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_error.expected=Variant::STRING; + return Variant(); + } + + StringName method = *p_args[0]; + + rpcp(method,&p_args[1],p_argcount-1); + + r_error.error=Variant::CallError::CALL_OK; + return Variant(); +} + +#endif +void Node::rpcp(int p_peer_id,bool p_unreliable,const StringName& p_method,const Variant** p_arg,int p_argcount) { + + ERR_FAIL_COND(!is_inside_tree()); + + bool skip_rpc=false; + + if (p_peer_id==0 || p_peer_id==get_tree()->get_network_unique_id() || (p_peer_id<0 && p_peer_id!=-get_tree()->get_network_unique_id())) { + //check that send mode can use local call + + + bool call_local=false; + + + + Map<StringName,RPCMode>::Element *E = data.rpc_methods.find(p_method); + if (E) { + + switch(E->get()) { + + case RPC_MODE_DISABLED: { + //do nothing + } break; + case RPC_MODE_REMOTE: { + //do nothing also, no need to call local + } break; + case RPC_MODE_SYNC: { + //call it, sync always results in call + call_local=true; + } break; + case RPC_MODE_MASTER: { + call_local=is_network_master(); + if (call_local) { + skip_rpc=true; //no other master so.. + } + } break; + case RPC_MODE_SLAVE: { + call_local=!is_network_master(); + } break; + + } + } + + + if (call_local) { + Variant::CallError ce; + call(p_method,p_arg,p_argcount,ce); + if (ce.error!=Variant::CallError::CALL_OK) { + String error = Variant::get_call_error_text(this,p_method,p_arg,p_argcount,ce); + error="rpc() aborted in local call: - "+error; + ERR_PRINTS(error); + return; + } + } else if (get_script_instance()){ + //attempt with script + ScriptInstance::RPCMode rpc_mode = get_script_instance()->get_rpc_mode(p_method); + + switch(rpc_mode) { + + case ScriptInstance::RPC_MODE_DISABLED: { + //do nothing + } break; + case ScriptInstance::RPC_MODE_REMOTE: { + //do nothing also, no need to call local + } break; + case ScriptInstance::RPC_MODE_SYNC: { + //call it, sync always results in call + call_local=true; + } break; + case ScriptInstance::RPC_MODE_MASTER: { + call_local=is_network_master(); + if (call_local) { + skip_rpc=true; //no other master so.. + } + } break; + case ScriptInstance::RPC_MODE_SLAVE: { + call_local=!is_network_master(); + } break; + } + + if (call_local) { + Variant::CallError ce; + ce.error=Variant::CallError::CALL_OK; + get_script_instance()->call(p_method,p_arg,p_argcount,ce); + if (ce.error!=Variant::CallError::CALL_OK) { + String error = Variant::get_call_error_text(this,p_method,p_arg,p_argcount,ce); + error="rpc() aborted in script local call: - "+error; + ERR_PRINTS(error); + return; + } + } + } + } + + if (skip_rpc) + return; + + + get_tree()->_rpc(this,p_peer_id,p_unreliable,false,p_method,p_arg,p_argcount); + +} + + +/******** RSET *********/ + + +void Node::rsetp(int p_peer_id,bool p_unreliable,const StringName& p_property,const Variant& p_value) { + + ERR_FAIL_COND(!is_inside_tree()); + + bool skip_rset=false; + + if (p_peer_id==0 || p_peer_id==get_tree()->get_network_unique_id() || (p_peer_id<0 && p_peer_id!=-get_tree()->get_network_unique_id())) { + //check that send mode can use local call + + + bool set_local=false; + + Map<StringName,RPCMode>::Element *E = data.rpc_properties.find(p_property); + if (E) { + + switch(E->get()) { + + case RPC_MODE_DISABLED: { + //do nothing + } break; + case RPC_MODE_REMOTE: { + //do nothing also, no need to call local + } break; + case RPC_MODE_SYNC: { + //call it, sync always results in call + set_local=true; + } break; + case RPC_MODE_MASTER: { + set_local=is_network_master(); + if (set_local) { + skip_rset=true; + } + + } break; + case RPC_MODE_SLAVE: { + set_local=!is_network_master(); + } break; + + } + } + + + if (set_local) { + bool valid; + set(p_property,p_value,&valid); + + if (!valid) { + String error="rset() aborted in local set, property not found: - "+String(p_property); + ERR_PRINTS(error); + return; + } + } else if (get_script_instance()){ + //attempt with script + ScriptInstance::RPCMode rpc_mode = get_script_instance()->get_rset_mode(p_property); + + switch(rpc_mode) { + + case ScriptInstance::RPC_MODE_DISABLED: { + //do nothing + } break; + case ScriptInstance::RPC_MODE_REMOTE: { + //do nothing also, no need to call local + } break; + case ScriptInstance::RPC_MODE_SYNC: { + //call it, sync always results in call + set_local=true; + } break; + case ScriptInstance::RPC_MODE_MASTER: { + set_local=is_network_master(); + if (set_local) { + skip_rset=true; + } + } break; + case ScriptInstance::RPC_MODE_SLAVE: { + set_local=!is_network_master(); + } break; + } + + if (set_local) { + + bool valid = get_script_instance()->set(p_property,p_value); + + if (!valid) { + String error="rset() aborted in local script set, property not found: - "+String(p_property); + ERR_PRINTS(error); + return; + } + } + + } + } + + if (skip_rset) + return; + + const Variant*vptr = &p_value; + + get_tree()->_rpc(this,p_peer_id,p_unreliable,true,p_property,&vptr,1); + +} + + + +void Node::rset(const StringName& p_property,const Variant& p_value) { + + rsetp(0,false,p_property,p_value); + +} + +void Node::rset_id(int p_peer_id,const StringName& p_property,const Variant& p_value) { + + rsetp(p_peer_id,false,p_property,p_value); + +} + +void Node::rset_unreliable(const StringName& p_property,const Variant& p_value) { + + rsetp(0,true,p_property,p_value); + +} + +void Node::rset_unreliable_id(int p_peer_id,const StringName& p_property,const Variant& p_value) { + + rsetp(p_peer_id,true,p_property,p_value); + +} + +//////////// end of rpc + +bool Node::can_call_rpc(const StringName& p_method) const { + + const Map<StringName,RPCMode>::Element *E = data.rpc_methods.find(p_method); + if (E) { + + switch(E->get()) { + + case RPC_MODE_DISABLED: { + return false; + } break; + case RPC_MODE_REMOTE: { + return true; + } break; + case RPC_MODE_SYNC: { + return true; + } break; + case RPC_MODE_MASTER: { + return is_network_master(); + } break; + case RPC_MODE_SLAVE: { + return !is_network_master(); + } break; + } + } + + + if (get_script_instance()){ + //attempt with script + ScriptInstance::RPCMode rpc_mode = get_script_instance()->get_rpc_mode(p_method); + + switch(rpc_mode) { + + case ScriptInstance::RPC_MODE_DISABLED: { + return false; + } break; + case ScriptInstance::RPC_MODE_REMOTE: { + return true; + } break; + case ScriptInstance::RPC_MODE_SYNC: { + return true; + } break; + case ScriptInstance::RPC_MODE_MASTER: { + return is_network_master(); + } break; + case ScriptInstance::RPC_MODE_SLAVE: { + return !is_network_master(); + } break; + } + + } + + ERR_PRINTS("RPC on unauthorized method attempted: "+String(p_method)+" on base: "+String(Variant(this))); + return false; +} + +bool Node::can_call_rset(const StringName& p_property) const { + + const Map<StringName,RPCMode>::Element *E = data.rpc_properties.find(p_property); + if (E) { + + switch(E->get()) { + + case RPC_MODE_DISABLED: { + return false; + } break; + case RPC_MODE_REMOTE: { + return true; + } break; + case RPC_MODE_SYNC: { + return true; + } break; + case RPC_MODE_MASTER: { + return is_network_master(); + } break; + case RPC_MODE_SLAVE: { + return !is_network_master(); + } break; + } + } + + + if (get_script_instance()){ + //attempt with script + ScriptInstance::RPCMode rpc_mode = get_script_instance()->get_rset_mode(p_property); + + switch(rpc_mode) { + + case ScriptInstance::RPC_MODE_DISABLED: { + return false; + } break; + case ScriptInstance::RPC_MODE_REMOTE: { + return true; + } break; + case ScriptInstance::RPC_MODE_SYNC: { + return true; + } break; + case ScriptInstance::RPC_MODE_MASTER: { + return is_network_master(); + } break; + case ScriptInstance::RPC_MODE_SLAVE: { + return !is_network_master(); + } break; + } + + } + + ERR_PRINTS("RSET on unauthorized property attempted: "+String(p_property)+" on base: "+String(Variant(this))); + + return false; +} + + bool Node::can_process() const { ERR_FAIL_COND_V( !is_inside_tree(), false ); @@ -567,6 +1227,8 @@ void Node::set_name(const String& p_name) { data.parent->_validate_child_name(this); } + propagate_notification(NOTIFICATION_PATH_CHANGED); + if (is_inside_tree()) { emit_signal("renamed"); @@ -1121,6 +1783,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()); @@ -1178,6 +1872,10 @@ NodePath Node::get_path_to(const Node *p_node) const { NodePath Node::get_path() const { ERR_FAIL_COND_V(!is_inside_tree(),NodePath()); + + if (data.path_cache) + return *data.path_cache; + const Node *n = this; Vector<StringName> path; @@ -1189,7 +1887,9 @@ NodePath Node::get_path() const { path.invert(); - return NodePath( path, true ); + data.path_cache = memnew( NodePath( path, true ) ); + + return *data.path_cache; } bool Node::is_in_group(const StringName& p_identifier) const { @@ -2180,7 +2880,13 @@ void Node::_bind_methods() { ObjectTypeDB::bind_method(_MD("queue_free"),&Node::queue_delete); + ObjectTypeDB::bind_method(_MD("set_network_mode","mode"),&Node::set_network_mode); + ObjectTypeDB::bind_method(_MD("get_network_mode"),&Node::get_network_mode); + + ObjectTypeDB::bind_method(_MD("is_network_master"),&Node::is_network_master); + ObjectTypeDB::bind_method(_MD("rpc_config","method","mode"),&Node::rpc_config); + ObjectTypeDB::bind_method(_MD("rset_config","property","mode"),&Node::rset_config); #ifdef TOOLS_ENABLED @@ -2190,6 +2896,33 @@ void Node::_bind_methods() { #endif + { + MethodInfo mi; + + mi.arguments.push_back( PropertyInfo( Variant::STRING, "method")); + + + mi.name="rpc"; + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"rpc",&Node::_rpc_bind,mi); + mi.name="rpc_unreliable"; + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"rpc_unreliable",&Node::_rpc_unreliable_bind,mi); + + mi.arguments.push_front( PropertyInfo( Variant::INT, "peer_id") ); + + mi.name="rpc_id"; + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"rpc_id",&Node::_rpc_id_bind,mi); + mi.name="rpc_unreliable_id"; + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"rpc_unreliable_id",&Node::_rpc_unreliable_id_bind,mi); + + + } + + ObjectTypeDB::bind_method(_MD("rset","property","value:Variant"),&Node::rset); + ObjectTypeDB::bind_method(_MD("rset_id","peer_id","property","value:Variant"),&Node::rset_id); + ObjectTypeDB::bind_method(_MD("rset_unreliable","property","value:Variant"),&Node::rset_unreliable); + ObjectTypeDB::bind_method(_MD("rset_unreliable_id","peer_id","property","value:Variant"),&Node::rset_unreliable_id); + + BIND_CONSTANT( NOTIFICATION_ENTER_TREE ); BIND_CONSTANT( NOTIFICATION_EXIT_TREE ); BIND_CONSTANT( NOTIFICATION_MOVED_IN_PARENT ); @@ -2204,8 +2937,18 @@ void Node::_bind_methods() { BIND_CONSTANT( NOTIFICATION_INSTANCED ); BIND_CONSTANT( NOTIFICATION_DRAG_BEGIN ); BIND_CONSTANT( NOTIFICATION_DRAG_END ); + BIND_CONSTANT( NOTIFICATION_PATH_CHANGED); + BIND_CONSTANT( NETWORK_MODE_INHERIT ); + BIND_CONSTANT( NETWORK_MODE_MASTER ); + BIND_CONSTANT( NETWORK_MODE_SLAVE ); + + BIND_CONSTANT( RPC_MODE_DISABLED ); + BIND_CONSTANT( RPC_MODE_REMOTE ); + BIND_CONSTANT( RPC_MODE_SYNC ); + BIND_CONSTANT( RPC_MODE_MASTER ); + BIND_CONSTANT( RPC_MODE_SLAVE ); BIND_CONSTANT( PAUSE_MODE_INHERIT ); BIND_CONSTANT( PAUSE_MODE_STOP ); @@ -2254,11 +2997,15 @@ Node::Node() { data.unhandled_key_input=false; data.pause_mode=PAUSE_MODE_INHERIT; data.pause_owner=NULL; + data.network_mode=NETWORK_MODE_INHERIT; + data.network_owner=NULL; + data.path_cache=NULL; data.parent_owned=false; data.in_constructor=true; data.viewport=NULL; data.use_placeholder=false; data.display_folded=false; + } Node::~Node() { diff --git a/scene/main/node.h b/scene/main/node.h index 10cfc5f9e6..3568da2ab0 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -53,6 +53,21 @@ public: PAUSE_MODE_PROCESS }; + enum NetworkMode { + + NETWORK_MODE_INHERIT, + NETWORK_MODE_MASTER, + NETWORK_MODE_SLAVE + }; + + enum RPCMode { + + RPC_MODE_DISABLED, //no rpc for this method, calls to this will be blocked (default) + RPC_MODE_REMOTE, // using rpc() on it will call method / set property in all other peers + RPC_MODE_SYNC, // using rpc() on it will call method / set property in all other peers and locally + RPC_MODE_MASTER, // usinc rpc() on it will call method on wherever the master is, be it local or remote + RPC_MODE_SLAVE, // usinc rpc() on it will call method for all slaves, be it local or remote + }; struct Comparator { @@ -68,6 +83,8 @@ private: GroupData() { persistent=false; } }; + + struct Data { String filename; @@ -98,6 +115,13 @@ private: PauseMode pause_mode; Node *pause_owner; + + NetworkMode network_mode; + Node *network_owner; + Map<StringName,RPCMode> rpc_methods; + Map<StringName,RPCMode> rpc_properties; + + // variables used to properly sort the node when processing, ignored otherwise //should move all the stuff below to bits bool fixed_process; @@ -113,6 +137,8 @@ private: bool display_folded; + mutable NodePath *path_cache; + } data; @@ -134,6 +160,7 @@ private: void _propagate_validate_owner(); void _print_stray_nodes(); void _propagate_pause_owner(Node*p_owner); + void _propagate_network_owner(Node*p_owner); Array _get_node_and_resource(const NodePath& p_path); void _duplicate_signals(const Node* p_original,Node* p_copy) const; @@ -143,6 +170,11 @@ private: Array _get_children() const; Array _get_groups() const; + Variant _rpc_bind(const Variant** p_args, int p_argcount, Variant::CallError& r_error); + Variant _rpc_unreliable_bind(const Variant** p_args, int p_argcount, Variant::CallError& r_error); + Variant _rpc_id_bind(const Variant** p_args, int p_argcount, Variant::CallError& r_error); + Variant _rpc_unreliable_id_bind(const Variant** p_args, int p_argcount, Variant::CallError& r_error); + friend class SceneTree; void _set_tree(SceneTree *p_tree); @@ -186,6 +218,7 @@ public: NOTIFICATION_INSTANCED=20, NOTIFICATION_DRAG_BEGIN=21, NOTIFICATION_DRAG_END=22, + NOTIFICATION_PATH_CHANGED=23, }; /* NODE/TREE */ @@ -215,6 +248,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); @@ -330,7 +364,32 @@ public: void set_display_folded(bool p_folded); bool is_displayed_folded() const; - /* CANVAS */ + /* NETWORK */ + + void set_network_mode(NetworkMode p_mode); + NetworkMode get_network_mode() const; + bool is_network_master() const; + + void rpc_config(const StringName& p_method,RPCMode p_mode); // config a local method for RPC + void rset_config(const StringName& p_property,RPCMode p_mode); // config a local property for RPC + + void rpc(const StringName& p_method,VARIANT_ARG_LIST); //rpc call, honors RPCMode + void rpc_unreliable(const StringName& p_method,VARIANT_ARG_LIST); //rpc call, honors RPCMode + void rpc_id(int p_peer_id,const StringName& p_method,VARIANT_ARG_LIST); //rpc call, honors RPCMode + void rpc_unreliable_id(int p_peer_id,const StringName& p_method,VARIANT_ARG_LIST); //rpc call, honors RPCMode + + void rpcp(int p_peer_id,bool p_unreliable,const StringName& p_method,const Variant** p_arg,int p_argcount); + + void rset(const StringName& p_property, const Variant& p_value); //remote set call, honors RPCMode + void rset_unreliable(const StringName& p_property,const Variant& p_value); //remote set call, honors RPCMode + void rset_id(int p_peer_id,const StringName& p_property,const Variant& p_value); //remote set call, honors RPCMode + void rset_unreliable_id(int p_peer_id,const StringName& p_property,const Variant& p_value); //remote set call, honors RPCMode + + void rsetp(int p_peer_id,bool p_unreliable,const StringName& p_property,const Variant& p_value); + + bool can_call_rpc(const StringName& p_method) const; + bool can_call_rset(const StringName& p_property) const; + Node(); ~Node(); diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp index a7ef7ca7c1..e3472c074a 100644 --- a/scene/main/scene_main_loop.cpp +++ b/scene/main/scene_main_loop.cpp @@ -44,6 +44,30 @@ #include "scene/resources/packed_scene.h" #include "scene/resources/material.h" #include "scene/resources/mesh.h" +#include "io/marshalls.h" + +void SceneTreeTimer::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_time_left","time"),&SceneTreeTimer::set_time_left); + ObjectTypeDB::bind_method(_MD("get_time_left"),&SceneTreeTimer::get_time_left); + + ADD_SIGNAL(MethodInfo("timeout")); +} + + +void SceneTreeTimer::set_time_left(float p_time) { + time_left=p_time; +} + +float SceneTreeTimer::get_time_left() const { + return time_left; +} + + +SceneTreeTimer::SceneTreeTimer() { + time_left=0; +} + void SceneTree::tree_changed() { @@ -521,6 +545,8 @@ bool SceneTree::idle(float p_time){ idle_process_time=p_time; + _network_poll(); + emit_signal("idle_frame"); _flush_transform_notifications(); @@ -547,6 +573,23 @@ bool SceneTree::idle(float p_time){ _flush_delete_queue(); + //go through timers + + for (List<Ref<SceneTreeTimer> >::Element *E=timers.front();E;) { + + List<Ref<SceneTreeTimer> >::Element *N = E->next(); + + float time_left = E->get()->get_time_left(); + time_left-=p_time; + E->get()->set_time_left(time_left); + + if (time_left<0) { + E->get()->emit_signal("timeout"); + timers.erase(E); + } + E=N; + } + return _quit; } @@ -1604,6 +1647,510 @@ void SceneTree::drop_files(const Vector<String>& p_files,int p_from_screen) { MainLoop::drop_files(p_files,p_from_screen); } + +Ref<SceneTreeTimer> SceneTree::create_timer(float p_delay_sec) { + + Ref<SceneTreeTimer> stt; + stt.instance(); + stt->set_time_left(p_delay_sec); + timers.push_back(stt); + return stt; +} + +void SceneTree::_network_peer_connected(int p_id) { + + + connected_peers.insert(p_id); + path_get_cache.insert(p_id,PathGetCache()); + + + emit_signal("network_peer_connected",p_id); +} + +void SceneTree::_network_peer_disconnected(int p_id) { + + connected_peers.erase(p_id); + path_get_cache.erase(p_id); //I no longer need your cache, sorry + emit_signal("network_peer_disconnected",p_id); +} + +void SceneTree::_connected_to_server() { + + emit_signal("connected_to_server"); +} + +void SceneTree::_connection_failed() { + + emit_signal("connection_failed"); +} + +void SceneTree::_server_disconnected() { + + emit_signal("server_disconnected"); +} + +void SceneTree::set_network_peer(const Ref<NetworkedMultiplayerPeer>& p_network_peer) { + if (network_peer.is_valid()) { + network_peer->disconnect("peer_connected",this,"_network_peer_connected"); + network_peer->disconnect("peer_disconnected",this,"_network_peer_disconnected"); + network_peer->disconnect("connection_succeeded",this,"_connected_to_server"); + network_peer->disconnect("connection_failed",this,"_connection_failed"); + network_peer->disconnect("server_disconnected",this,"_server_disconnected"); + connected_peers.clear(); + path_get_cache.clear(); + path_send_cache.clear(); + last_send_cache_id=1; + } + + ERR_EXPLAIN("Supplied NetworkedNetworkPeer must be connecting or connected."); + ERR_FAIL_COND(p_network_peer.is_valid() && p_network_peer->get_connection_status()==NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED); + + network_peer=p_network_peer; + + if (network_peer.is_valid()) { + network_peer->connect("peer_connected",this,"_network_peer_connected"); + network_peer->connect("peer_disconnected",this,"_network_peer_disconnected"); + network_peer->connect("connection_succeeded",this,"_connected_to_server"); + network_peer->connect("connection_failed",this,"_connection_failed"); + network_peer->connect("server_disconnected",this,"_server_disconnected"); + } +} + +bool SceneTree::is_network_server() const { + + ERR_FAIL_COND_V(!network_peer.is_valid(),false); + return network_peer->is_server(); + +} + +int SceneTree::get_network_unique_id() const { + + ERR_FAIL_COND_V(!network_peer.is_valid(),0); + return network_peer->get_unique_id(); +} + +void SceneTree::set_refuse_new_network_connections(bool p_refuse) { + ERR_FAIL_COND(!network_peer.is_valid()); + network_peer->set_refuse_new_connections(p_refuse); +} + +bool SceneTree::is_refusing_new_network_connections() const { + + ERR_FAIL_COND_V(!network_peer.is_valid(),false); + + return network_peer->is_refusing_new_connections(); + +} + + +void SceneTree::_rpc(Node* p_from,int p_to,bool p_unreliable,bool p_set,const StringName& p_name,const Variant** p_arg,int p_argcount) { + + if (network_peer.is_null()) { + ERR_EXPLAIN("Attempt to remote call/set when networking is not active in SceneTree."); + ERR_FAIL(); + } + + if (network_peer->get_connection_status()==NetworkedMultiplayerPeer::CONNECTION_CONNECTING) { + ERR_EXPLAIN("Attempt to remote call/set when networking is not connected yet in SceneTree."); + ERR_FAIL(); + } + + if (network_peer->get_connection_status()==NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED) { + ERR_EXPLAIN("Attempt to remote call/set when networking is disconnected."); + ERR_FAIL(); + } + + if (p_argcount>255) { + ERR_EXPLAIN("Too many arguments >255."); + ERR_FAIL(); + } + + if (p_to!=0 && !connected_peers.has(ABS(p_to))) { + if (p_to==get_network_unique_id()) { + ERR_EXPLAIN("Attempt to remote call/set yourself! unique ID: "+itos(get_network_unique_id())); + } else { + ERR_EXPLAIN("Attempt to remote call unexisting ID: "+itos(p_to)); + + } + + ERR_FAIL(); + } + + NodePath from_path = p_from->get_path(); + ERR_FAIL_COND(from_path.is_empty()); + + + + //see if the path is cached + PathSentCache *psc = path_send_cache.getptr(from_path); + if (!psc) { + //path is not cached, create + path_send_cache[from_path]=PathSentCache(); + psc = path_send_cache.getptr(from_path); + psc->id=last_send_cache_id++; + + } + + + //create base packet, lots of harcode because it must be tight + + int ofs=0; + +#define MAKE_ROOM(m_amount) if (packet_cache.size() < m_amount) packet_cache.resize(m_amount); + + //encode type + MAKE_ROOM(1); + packet_cache[0]=p_set ? NETWORK_COMMAND_REMOTE_SET : NETWORK_COMMAND_REMOTE_CALL; + ofs+=1; + + //encode ID + MAKE_ROOM(ofs+4); + encode_uint32(psc->id,&packet_cache[ofs]); + ofs+=4; + + //encode function name + CharString name = String(p_name).utf8(); + int len = encode_cstring(name.get_data(),NULL); + MAKE_ROOM(ofs+len); + encode_cstring(name.get_data(),&packet_cache[ofs]); + ofs+=len; + + if (p_set) { + //set argument + Error err = encode_variant(*p_arg[0],NULL,len); + ERR_FAIL_COND(err!=OK); + MAKE_ROOM(ofs+len); + encode_variant(*p_arg[0],&packet_cache[ofs],len); + ofs+=len; + + } else { + //call arguments + MAKE_ROOM(ofs+1); + packet_cache[ofs]=p_argcount; + ofs+=1; + for(int i=0;i<p_argcount;i++) { + Error err = encode_variant(*p_arg[i],NULL,len); + ERR_FAIL_COND(err!=OK); + MAKE_ROOM(ofs+len); + encode_variant(*p_arg[i],&packet_cache[ofs],len); + ofs+=len; + } + + } + + //see if all peers have cached path (is so, call can be fast) + bool has_all_peers=true; + + List<int> peers_to_add; //if one is missing, take note to add it + + for (Set<int>::Element *E=connected_peers.front();E;E=E->next()) { + + if (p_to<0 && E->get()==-p_to) + continue; //continue, excluded + + if (p_to>0 && E->get()!=p_to) + continue; //continue, not for this peer + + Map<int,bool>::Element *F = psc->confirmed_peers.find(E->get()); + + if (!F || F->get()==false) { + //path was not cached, or was cached but is unconfirmed + if (!F) { + //not cached at all, take note + peers_to_add.push_back(E->get()); + } + + has_all_peers=false; + } + } + + //those that need to be added, send a message for this + + for (List<int>::Element *E=peers_to_add.front();E;E=E->next()) { + + //encode function name + CharString pname = String(from_path).utf8(); + int len = encode_cstring(pname.get_data(),NULL); + + Vector<uint8_t> packet; + + packet.resize(1+4+len); + packet[0]=NETWORK_COMMAND_SIMPLIFY_PATH; + encode_uint32(psc->id,&packet[1]); + encode_cstring(pname.get_data(),&packet[5]); + + network_peer->set_target_peer(E->get()); //to all of you + network_peer->set_transfer_mode(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE); + network_peer->put_packet(packet.ptr(),packet.size()); + + psc->confirmed_peers.insert(E->get(),false); //insert into confirmed, but as false since it was not confirmed + } + + //take chance and set transfer mode, since all send methods will use it + network_peer->set_transfer_mode(p_unreliable ? NetworkedMultiplayerPeer::TRANSFER_MODE_UNRELIABLE : NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE); + + if (has_all_peers) { + + //they all have verified paths, so send fast + network_peer->set_target_peer(p_to); //to all of you + network_peer->put_packet(packet_cache.ptr(),ofs); //a message with love + } else { + //not all verified path, so send one by one + + //apend path at the end, since we will need it for some packets + CharString pname = String(from_path).utf8(); + int path_len = encode_cstring(pname.get_data(),NULL); + MAKE_ROOM(ofs+path_len); + encode_cstring(pname.get_data(),&packet_cache[ofs]); + + + for (Set<int>::Element *E=connected_peers.front();E;E=E->next()) { + + if (p_to<0 && E->get()==-p_to) + continue; //continue, excluded + + if (p_to>0 && E->get()!=p_to) + continue; //continue, not for this peer + + Map<int,bool>::Element *F = psc->confirmed_peers.find(E->get()); + ERR_CONTINUE(!F);//should never happen + + network_peer->set_target_peer(E->get()); //to this one specifically + + if (F->get()==true) { + //this one confirmed path, so use id + encode_uint32(psc->id,&packet_cache[1]); + network_peer->put_packet(packet_cache.ptr(),ofs); + } else { + //this one did not confirm path yet, so use entire path (sorry!) + encode_uint32(0x80000000|ofs,&packet_cache[1]); //offset to path and flag + network_peer->put_packet(packet_cache.ptr(),ofs+path_len); + } + + } + } +} + + +void SceneTree::_network_process_packet(int p_from, const uint8_t* p_packet, int p_packet_len) { + + ERR_FAIL_COND(p_packet_len<5); + + uint8_t packet_type = p_packet[0]; + + switch(packet_type) { + + case NETWORK_COMMAND_REMOTE_CALL: + case NETWORK_COMMAND_REMOTE_SET: { + + ERR_FAIL_COND(p_packet_len<5); + uint32_t target = decode_uint32(&p_packet[1]); + + + Node *node=NULL; + + if (target&0x80000000) { + + int ofs = target&0x7FFFFFFF; + ERR_FAIL_COND(ofs>=p_packet_len); + + String paths; + paths.parse_utf8((const char*)&p_packet[ofs],p_packet_len-ofs); + + NodePath np = paths; + + node = get_root()->get_node(np); + if (node==NULL) { + ERR_EXPLAIN("Failed to get path from RPC: "+String(np)); + ERR_FAIL_COND(node==NULL); + } + } else { + + int id = target; + + Map<int,PathGetCache>::Element *E=path_get_cache.find(p_from); + ERR_FAIL_COND(!E); + + Map<int,PathGetCache::NodeInfo>::Element *F=E->get().nodes.find(id); + ERR_FAIL_COND(!F); + + PathGetCache::NodeInfo *ni = &F->get(); + //do proper caching later + + node = get_root()->get_node(ni->path); + if (node==NULL) { + ERR_EXPLAIN("Failed to get cached path from RPC: "+String(ni->path)); + ERR_FAIL_COND(node==NULL); + } + + + } + + ERR_FAIL_COND(p_packet_len<6); + + //detect cstring end + int len_end=5; + for(;len_end<p_packet_len;len_end++) { + if (p_packet[len_end]==0) { + break; + } + } + + ERR_FAIL_COND(len_end>=p_packet_len); + + StringName name = String::utf8((const char*)&p_packet[5]); + + + + + if (packet_type==NETWORK_COMMAND_REMOTE_CALL) { + + if (!node->can_call_rpc(name)) + return; + + int ofs = len_end+1; + + ERR_FAIL_COND(ofs>=p_packet_len); + + int argc = p_packet[ofs]; + Vector<Variant> args; + Vector<const Variant*> argp; + args.resize(argc); + argp.resize(argc); + + ofs++; + + for(int i=0;i<argc;i++) { + + ERR_FAIL_COND(ofs>=p_packet_len); + int vlen; + Error err = decode_variant(args[i],&p_packet[ofs],p_packet_len-ofs,&vlen); + ERR_FAIL_COND(err!=OK); + //args[i]=p_packet[3+i]; + argp[i]=&args[i]; + ofs+=vlen; + } + + Variant::CallError ce; + + node->call(name,argp.ptr(),argc,ce); + if (ce.error!=Variant::CallError::CALL_OK) { + String error = Variant::get_call_error_text(node,name,argp.ptr(),argc,ce); + error="RPC - "+error; + ERR_PRINTS(error); + } + + } else { + + if (!node->can_call_rset(name)) + return; + + int ofs = len_end+1; + + ERR_FAIL_COND(ofs>=p_packet_len); + + Variant value; + decode_variant(value,&p_packet[ofs],p_packet_len-ofs); + + bool valid; + + node->set(name,value,&valid); + if (!valid) { + String error = "Error setting remote property '"+String(name)+"', not found in object of type "+node->get_type(); + ERR_PRINTS(error); + } + } + + } break; + case NETWORK_COMMAND_SIMPLIFY_PATH: { + + ERR_FAIL_COND(p_packet_len<5); + int id = decode_uint32(&p_packet[1]); + + String paths; + paths.parse_utf8((const char*)&p_packet[5],p_packet_len-5); + + NodePath path = paths; + + if (!path_get_cache.has(p_from)) { + path_get_cache[p_from]=PathGetCache(); + } + + PathGetCache::NodeInfo ni; + ni.path=path; + ni.instance=0; + + path_get_cache[p_from].nodes[id]=ni; + + + { + //send ack + + //encode path + CharString pname = String(path).utf8(); + int len = encode_cstring(pname.get_data(),NULL); + + Vector<uint8_t> packet; + + packet.resize(1+len); + packet[0]=NETWORK_COMMAND_CONFIRM_PATH; + encode_cstring(pname.get_data(),&packet[1]); + + network_peer->set_transfer_mode(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE); + network_peer->set_target_peer(p_from); + network_peer->put_packet(packet.ptr(),packet.size()); + } + } break; + case NETWORK_COMMAND_CONFIRM_PATH: { + + String paths; + paths.parse_utf8((const char*)&p_packet[1],p_packet_len-1); + + NodePath path = paths; + + PathSentCache *psc = path_send_cache.getptr(path); + ERR_FAIL_COND(!psc); + + Map<int,bool>::Element *E=psc->confirmed_peers.find(p_from); + ERR_FAIL_COND(!E); + E->get()=true; + } break; + } + +} + +void SceneTree::_network_poll() { + + if (!network_peer.is_valid() || network_peer->get_connection_status()==NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED) + return; + + network_peer->poll(); + + if (!network_peer.is_valid()) //it's possible that polling might have resulted in a disconnection, so check here + return; + + while(network_peer->get_available_packet_count()) { + + int sender = network_peer->get_packet_peer(); + const uint8_t *packet; + int len; + + Error err = network_peer->get_packet(&packet,len); + if (err!=OK) { + ERR_PRINT("Error getting packet!"); + } + + _network_process_packet(sender,packet,len); + + if (!network_peer.is_valid()) { + break; //it's also possible that a packet or RPC caused a disconnection, so also check here + } + } + + +} + + void SceneTree::_bind_methods() { @@ -1634,6 +2181,8 @@ void SceneTree::_bind_methods() { ObjectTypeDB::bind_method(_MD("is_paused"),&SceneTree::is_paused); ObjectTypeDB::bind_method(_MD("set_input_as_handled"),&SceneTree::set_input_as_handled); + ObjectTypeDB::bind_method(_MD("create_timer:SceneTreeTimer","time_sec"),&SceneTree::create_timer); + ObjectTypeDB::bind_method(_MD("get_node_count"),&SceneTree::get_node_count); ObjectTypeDB::bind_method(_MD("get_frame"),&SceneTree::get_frame); @@ -1651,13 +2200,9 @@ void SceneTree::_bind_methods() { mi.arguments.push_back( PropertyInfo( Variant::INT, "flags")); mi.arguments.push_back( PropertyInfo( Variant::STRING, "group")); mi.arguments.push_back( PropertyInfo( Variant::STRING, "method")); - Vector<Variant> defargs; - for(int i=0;i<VARIANT_ARG_MAX;i++) { - mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i))); - defargs.push_back(Variant()); - } - ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call_group",&SceneTree::_call_group,mi,defargs); + + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"call_group",&SceneTree::_call_group,mi); ObjectTypeDB::bind_method(_MD("set_current_scene","child_node:Node"),&SceneTree::set_current_scene); ObjectTypeDB::bind_method(_MD("get_current_scene:Node"),&SceneTree::get_current_scene); @@ -1669,6 +2214,18 @@ void SceneTree::_bind_methods() { ObjectTypeDB::bind_method(_MD("_change_scene"),&SceneTree::_change_scene); + + ObjectTypeDB::bind_method(_MD("set_network_peer","peer:NetworkedMultiplayerPeer"),&SceneTree::set_network_peer); + ObjectTypeDB::bind_method(_MD("is_network_server"),&SceneTree::is_network_server); + ObjectTypeDB::bind_method(_MD("get_network_unique_id"),&SceneTree::get_network_unique_id); + ObjectTypeDB::bind_method(_MD("set_refuse_new_network_connections","refuse"),&SceneTree::set_refuse_new_network_connections); + ObjectTypeDB::bind_method(_MD("is_refusing_new_network_connections"),&SceneTree::is_refusing_new_network_connections); + ObjectTypeDB::bind_method(_MD("_network_peer_connected"),&SceneTree::_network_peer_connected); + ObjectTypeDB::bind_method(_MD("_network_peer_disconnected"),&SceneTree::_network_peer_disconnected); + ObjectTypeDB::bind_method(_MD("_connected_to_server"),&SceneTree::_connected_to_server); + ObjectTypeDB::bind_method(_MD("_connection_failed"),&SceneTree::_connection_failed); + ObjectTypeDB::bind_method(_MD("_server_disconnected"),&SceneTree::_server_disconnected); + ADD_SIGNAL( MethodInfo("tree_changed") ); ADD_SIGNAL( MethodInfo("node_removed",PropertyInfo( Variant::OBJECT, "node") ) ); ADD_SIGNAL( MethodInfo("screen_resized") ); @@ -1678,6 +2235,11 @@ void SceneTree::_bind_methods() { ADD_SIGNAL( MethodInfo("fixed_frame")); ADD_SIGNAL( MethodInfo("files_dropped",PropertyInfo(Variant::STRING_ARRAY,"files"),PropertyInfo(Variant::INT,"screen")) ); + ADD_SIGNAL( MethodInfo("network_peer_connected",PropertyInfo(Variant::INT,"id"))); + ADD_SIGNAL( MethodInfo("network_peer_disconnected",PropertyInfo(Variant::INT,"id"))); + ADD_SIGNAL( MethodInfo("connected_to_server")); + ADD_SIGNAL( MethodInfo("connection_failed")); + ADD_SIGNAL( MethodInfo("server_disconnected")); BIND_CONSTANT( GROUP_CALL_DEFAULT ); BIND_CONSTANT( GROUP_CALL_REVERSE ); @@ -1778,6 +2340,8 @@ SceneTree::SceneTree() { live_edit_root=NodePath("/root"); + last_send_cache_id=1; + #endif diff --git a/scene/main/scene_main_loop.h b/scene/main/scene_main_loop.h index 38d13c0447..1c0f88862c 100644 --- a/scene/main/scene_main_loop.h +++ b/scene/main/scene_main_loop.h @@ -35,6 +35,9 @@ #include "scene/resources/world_2d.h" #include "os/thread_safe.h" #include "self_list.h" +#include "io/networked_multiplayer_peer.h" + + /** @author Juan Linietsky <reduzio@gmail.com> */ @@ -47,6 +50,22 @@ class Viewport; class Material; class Mesh; + + +class SceneTreeTimer : public Reference { + OBJ_TYPE(SceneTreeTimer,Reference); + + float time_left; +protected: + static void _bind_methods(); +public: + + void set_time_left(float p_time); + float get_time_left() const; + + SceneTreeTimer(); +}; + class SceneTree : public MainLoop { _THREAD_SAFE_CLASS_ @@ -155,9 +174,62 @@ private: void _change_scene(Node* p_to); //void _call_group(uint32_t p_call_flags,const StringName& p_group,const StringName& p_function,const Variant& p_arg1,const Variant& p_arg2); + List<Ref<SceneTreeTimer> > timers; + + + ///network/// + + enum NetworkCommands { + NETWORK_COMMAND_REMOTE_CALL, + NETWORK_COMMAND_REMOTE_SET, + NETWORK_COMMAND_SIMPLIFY_PATH, + NETWORK_COMMAND_CONFIRM_PATH, + }; + + Ref<NetworkedMultiplayerPeer> network_peer; + + Set<int> connected_peers; + void _network_peer_connected(int p_id); + void _network_peer_disconnected(int p_id); + + void _connected_to_server(); + void _connection_failed(); + void _server_disconnected(); + + //path sent caches + struct PathSentCache { + Map<int,bool> confirmed_peers; + int id; + }; + + HashMap<NodePath,PathSentCache> path_send_cache; + int last_send_cache_id; + + //path get caches + struct PathGetCache { + struct NodeInfo { + NodePath path; + ObjectID instance; + }; + + Map<int,NodeInfo> nodes; + }; + + Map<int,PathGetCache> path_get_cache; + + Vector<uint8_t> packet_cache; + + void _network_process_packet(int p_from, const uint8_t *p_packet, int p_packet_len); + void _network_poll(); + static SceneTree *singleton; friend class Node; + + + + void _rpc(Node* p_from,int p_to,bool p_unreliable,bool p_set,const StringName& p_name,const Variant** p_arg,int p_argcount); + void tree_changed(); void node_removed(Node *p_node); @@ -233,6 +305,7 @@ friend class Viewport; #endif protected: + void _notification(int p_notification); static void _bind_methods(); @@ -339,6 +412,8 @@ public: Error change_scene_to(const Ref<PackedScene>& p_scene); Error reload_current_scene(); + Ref<SceneTreeTimer> create_timer(float p_delay_sec); + //used by Main::start, don't use otherwise void add_current_scene(Node * p_current); @@ -346,6 +421,15 @@ public: void drop_files(const Vector<String>& p_files,int p_from_screen=0); + //network API + + void set_network_peer(const Ref<NetworkedMultiplayerPeer>& p_network_peer); + bool is_network_server() const; + int get_network_unique_id() const; + + void set_refuse_new_network_connections(bool p_refuse); + bool is_refusing_new_network_connections() const; + SceneTree(); ~SceneTree(); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index bb6e6e289b..7970229c06 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -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; @@ -1755,7 +1782,6 @@ void Viewport::_gui_input_event(InputEvent p_event) { 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 } @@ -2007,8 +2033,22 @@ void Viewport::_gui_input_event(InputEvent p_event) { } + bool is_tooltip_shown = false; + + if (gui.tooltip_popup) { + if (can_tooltip) { + String tooltip = over->get_tooltip(gui.tooltip->get_global_transform().xform_inv(mpos)); + + if (tooltip.length() == 0) + _gui_cancel_tooltip(); + else if (tooltip == gui.tooltip_label->get_text()) + is_tooltip_shown = true; + } + else + _gui_cancel_tooltip(); + } - if (can_tooltip) { + if (can_tooltip && !is_tooltip_shown) { gui.tooltip=over; gui.tooltip_pos=mpos;//(parent_xform * get_transform()).affine_inverse().xform(pos); @@ -2035,7 +2075,6 @@ 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(); @@ -2056,6 +2095,7 @@ void Viewport::_gui_input_event(InputEvent p_event) { } break; case InputEvent::ACTION: case InputEvent::JOYSTICK_BUTTON: + case InputEvent::JOYSTICK_MOTION: case InputEvent::KEY: { @@ -2075,7 +2115,7 @@ void Viewport::_gui_input_event(InputEvent p_event) { if (gui.key_event_accepted) { - get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID); + get_tree()->set_input_as_handled(); break; } } @@ -2135,7 +2175,7 @@ void Viewport::_gui_input_event(InputEvent p_event) { if (next) { next->grab_focus(); - get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID); + get_tree()->set_input_as_handled(); } } @@ -2328,8 +2368,7 @@ void Viewport::_gui_control_grab_focus(Control* p_control) { if (gui.key_focus && gui.key_focus==p_control) return; - _gui_remove_focus(); - get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_gui_remove_focus"); + get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"_viewports","_gui_remove_focus"); gui.key_focus=p_control; p_control->notification(Control::NOTIFICATION_FOCUS_ENTER); p_control->update(); @@ -2637,6 +2676,7 @@ void Viewport::_bind_methods() { ObjectTypeDB::bind_method(_MD("is_input_disabled"), &Viewport::is_input_disabled); ObjectTypeDB::bind_method(_MD("_gui_show_tooltip"), &Viewport::_gui_show_tooltip); + ObjectTypeDB::bind_method(_MD("_gui_remove_focus"), &Viewport::_gui_remove_focus); ADD_PROPERTY( PropertyInfo(Variant::RECT2,"rect"), _SCS("set_rect"), _SCS("get_rect") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"own_world"), _SCS("set_use_own_world"), _SCS("is_using_own_world") ); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 56e40679b2..d22c3bad14 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -634,15 +634,16 @@ void register_scene_types() { ObjectTypeDB::register_type<PackedScene>(); ObjectTypeDB::register_type<SceneTree>(); + ObjectTypeDB::register_virtual_type<SceneTreeTimer>(); //sorry, you can't create it OS::get_singleton()->yield(); //may take time to init 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/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 182bc5dabc..03f28bef08 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; @@ -481,6 +485,7 @@ 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")); @@ -621,22 +626,32 @@ void fill_default_theme(Ref<Theme>& t,const Ref<Font> & default_font,const Ref<F // GraphNode - Ref<StyleBoxTexture> graphsb = make_stylebox(graph_node_png,6,24,6,5,3,24,16,5); - Ref<StyleBoxTexture> graphsbselected = make_stylebox(graph_node_selected_png,6,24,6,5,3,24,16,5); + Ref<StyleBoxTexture> graphsb = make_stylebox(graph_node_png,6,24,6,5,16,24,16,5); + Ref<StyleBoxTexture> graphsbcomment = make_stylebox(graph_node_comment_png,6,24,6,5,16,24,16,5); + Ref<StyleBoxTexture> graphsbcommentselected = make_stylebox(graph_node_comment_focus_png,6,24,6,5,16,24,16,5); + Ref<StyleBoxTexture> graphsbselected = make_stylebox(graph_node_selected_png,6,24,6,5,16,24,16,5); Ref<StyleBoxTexture> graphsbdefault = make_stylebox(graph_node_default_png,4,4,4,4,6,4,4,4); Ref<StyleBoxTexture> graphsbdeffocus = make_stylebox(graph_node_default_focus_png,4,4,4,4,6,4,4,4); + Ref<StyleBoxTexture> graph_bpoint = make_stylebox(graph_node_breakpoint_png,6,24,6,5,16,24,16,5); + Ref<StyleBoxTexture> graph_position = make_stylebox(graph_node_position_png,6,24,6,5,16,24,16,5); + //graphsb->set_expand_margin_size(MARGIN_LEFT,10); //graphsb->set_expand_margin_size(MARGIN_RIGHT,10); t->set_stylebox("frame","GraphNode", graphsb ); t->set_stylebox("selectedframe","GraphNode", graphsbselected ); t->set_stylebox("defaultframe", "GraphNode", graphsbdefault ); t->set_stylebox("defaultfocus", "GraphNode", graphsbdeffocus ); + t->set_stylebox("comment", "GraphNode", graphsbcomment ); + t->set_stylebox("commentfocus", "GraphNode", graphsbcommentselected ); + t->set_stylebox("breakpoint", "GraphNode", graph_bpoint ); + t->set_stylebox("position", "GraphNode", graph_position ); t->set_constant("separation","GraphNode", 1 *scale); t->set_icon("port","GraphNode", make_icon( graph_port_png ) ); t->set_icon("close","GraphNode", make_icon( graph_node_close_png ) ); + t->set_icon("resizer","GraphNode", make_icon( window_resizer_png ) ); t->set_font("title_font","GraphNode", default_font ); t->set_color("title_color","GraphNode", Color(0,0,0,1)); - t->set_constant("title_offset","GraphNode", 18 *scale); + t->set_constant("title_offset","GraphNode", 20 *scale); t->set_constant("close_offset","GraphNode", 18 *scale); t->set_constant("port_offset","GraphNode", 3 *scale); @@ -916,7 +931,12 @@ void fill_default_theme(Ref<Theme>& t,const Ref<Font> & default_font,const Ref<F t->set_icon("minus","GraphEdit", make_icon(icon_zoom_less_png) ); t->set_icon("reset","GraphEdit", make_icon(icon_zoom_reset_png) ); t->set_icon("more","GraphEdit", make_icon(icon_zoom_more_png) ); + t->set_icon("snap","GraphEdit", make_icon(icon_snap_png) ); t->set_stylebox("bg","GraphEdit", make_stylebox( tree_bg_png,4,4,4,5) ); + t->set_color("grid_minor","GraphEdit", Color(1,1,1,0.05) ); + t->set_color("grid_major","GraphEdit", Color(1,1,1,0.2) ); + t->set_constant("bezier_len_pos","GraphEdit", 80*scale ); + t->set_constant("bezier_len_neg","GraphEdit", 160*scale ); diff --git a/scene/resources/default_theme/graph_node.png b/scene/resources/default_theme/graph_node.png Binary files differindex 5eea134b25..d4b4dd3c1f 100644 --- a/scene/resources/default_theme/graph_node.png +++ b/scene/resources/default_theme/graph_node.png diff --git a/scene/resources/default_theme/graph_node_breakpoint.png b/scene/resources/default_theme/graph_node_breakpoint.png Binary files differnew file mode 100644 index 0000000000..0e36f31bd4 --- /dev/null +++ b/scene/resources/default_theme/graph_node_breakpoint.png diff --git a/scene/resources/default_theme/graph_node_comment.png b/scene/resources/default_theme/graph_node_comment.png Binary files differnew file mode 100644 index 0000000000..f2d6daa259 --- /dev/null +++ b/scene/resources/default_theme/graph_node_comment.png diff --git a/scene/resources/default_theme/graph_node_comment_focus.png b/scene/resources/default_theme/graph_node_comment_focus.png Binary files differnew file mode 100644 index 0000000000..a4b7b5a618 --- /dev/null +++ b/scene/resources/default_theme/graph_node_comment_focus.png diff --git a/scene/resources/default_theme/graph_node_position.png b/scene/resources/default_theme/graph_node_position.png Binary files differnew file mode 100644 index 0000000000..7ec15e2ff4 --- /dev/null +++ b/scene/resources/default_theme/graph_node_position.png diff --git a/scene/resources/default_theme/graph_node_selected.png b/scene/resources/default_theme/graph_node_selected.png Binary files differindex 22fdc7e89f..f76c9703dd 100644 --- a/scene/resources/default_theme/graph_node_selected.png +++ b/scene/resources/default_theme/graph_node_selected.png diff --git a/scene/resources/default_theme/graph_port.png b/scene/resources/default_theme/graph_port.png Binary files differindex 445e8548ce..9d5082cfdb 100644 --- a/scene/resources/default_theme/graph_port.png +++ b/scene/resources/default_theme/graph_port.png diff --git a/scene/resources/default_theme/icon_snap.png b/scene/resources/default_theme/icon_snap.png Binary files differnew file mode 100644 index 0000000000..93194d34e7 --- /dev/null +++ b/scene/resources/default_theme/icon_snap.png diff --git a/scene/resources/default_theme/source/graph_port.svg b/scene/resources/default_theme/source/graph_port.svg new file mode 100644 index 0000000000..de9b1d4827 --- /dev/null +++ b/scene/resources/default_theme/source/graph_port.svg @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="10" + height="10" + viewBox="0 0 10 10" + id="svg2" + version="1.1" + inkscape:version="0.91 r13725" + inkscape:export-filename="/home/djrm/Projects/godot/tools/editor/icons/icon_collapse.png" + inkscape:export-xdpi="45" + inkscape:export-ydpi="45" + sodipodi:docname="graph_port.svg"> + <defs + id="defs4" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="32.000001" + inkscape:cx="-5.0080069" + inkscape:cy="6.2185379" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="true" + units="px" + inkscape:snap-bbox="true" + inkscape:bbox-paths="true" + inkscape:bbox-nodes="true" + inkscape:snap-bbox-edge-midpoints="true" + inkscape:snap-bbox-midpoints="false" + inkscape:snap-object-midpoints="true" + inkscape:snap-center="true" + inkscape:window-width="1920" + inkscape:window-height="1016" + inkscape:window-x="0" + inkscape:window-y="27" + inkscape:window-maximized="1" + inkscape:snap-smooth-nodes="true" + inkscape:object-nodes="true"> + <inkscape:grid + type="xygrid" + id="grid3336" /> + </sodipodi:namedview> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(0,-1042.3622)"> + <circle + style="fill:#f3f3f3;fill-rule:evenodd;stroke:#d8d8d8;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;fill-opacity:1" + id="path3335" + cx="5" + cy="1047.3622" + r="4" /> + </g> +</svg> diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h index ab758f72b4..73c801483f 100644 --- a/scene/resources/default_theme/theme_data.h +++ b/scene/resources/default_theme/theme_data.h @@ -5,12 +5,12 @@ static const unsigned char arrow_down_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0xc,0x8,0x4,0x0,0x0,0x0,0xfc,0x7c,0x94,0x6c,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x4,0x4e,0x1d,0x2,0xaf,0x0,0x0,0x0,0x4a,0x49,0x44,0x41,0x54,0x18,0xd3,0x63,0x60,0xa0,0x1a,0x60,0x64,0x60,0x60,0x60,0x78,0xf0,0x1f,0x55,0x50,0x81,0x91,0x81,0x81,0x9,0x97,0xe,0xfc,0x12,0x8c,0xf1,0xc,0x5f,0xe1,0x22,0xdf,0x19,0xd3,0x91,0xe4,0xef,0x6b,0xdc,0xbf,0xf4,0xe0,0xff,0x83,0xff,0xf,0xae,0x3f,0xd6,0x45,0xb2,0x9c,0x81,0x81,0x81,0xe1,0x5,0xf7,0xcf,0x29,0xc,0xc,0xec,0x39,0x12,0x5f,0x19,0xa8,0xd,0x0,0x99,0x85,0x11,0xfa,0x28,0xbe,0xff,0xef,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xba,0x84,0x14,0xff,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xcb,0xd9,0xac,0x43,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0xc,0x8,0x6,0x0,0x0,0x0,0x56,0x75,0x5c,0xe7,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x6d,0x49,0x44,0x41,0x54,0x28,0x91,0x63,0x60,0x18,0x74,0x80,0x11,0xc6,0x78,0xf0,0xe0,0xc1,0x7f,0x7c,0xa,0x15,0x14,0x14,0x18,0x19,0x18,0x18,0x18,0x98,0x48,0xb5,0x81,0x7c,0xd,0x8c,0x8c,0x8c,0xf1,0xc,0xc,0xc,0x5f,0xb1,0xa8,0xf9,0xce,0xc8,0xc8,0x98,0xe,0x57,0x87,0x2c,0x73,0xff,0xfe,0x7d,0xd,0x6,0x6,0x86,0x55,0x8c,0x8c,0x8c,0xba,0x50,0xa1,0x1b,0xcc,0xcc,0xcc,0x61,0xb2,0xb2,0xb2,0x97,0xb1,0x6a,0x60,0x60,0x60,0x60,0x78,0xf1,0xe2,0x5,0xf7,0xcf,0x9f,0x3f,0xa7,0x30,0x30,0x30,0x30,0xb0,0xb3,0xb3,0xe7,0x48,0x48,0x48,0x60,0xb3,0x75,0x30,0x1,0x0,0x28,0x20,0x14,0xc2,0x1b,0xd0,0x7c,0xca,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char arrow_right_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0xc,0x8,0x4,0x0,0x0,0x0,0xfc,0x7c,0x94,0x6c,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x4e,0x49,0x44,0x41,0x54,0x18,0xd3,0x63,0x60,0x20,0x13,0x3c,0xf8,0xff,0xe0,0xff,0x83,0xff,0xf7,0x13,0x10,0x22,0x8c,0x30,0x9,0x6,0x6,0x6,0x6,0x86,0xaf,0x8c,0xe6,0xf2,0x57,0x21,0x22,0x4c,0x28,0x1a,0xb9,0xff,0xaf,0x7a,0xc1,0x8d,0x4d,0x82,0x81,0x41,0xeb,0xe7,0x14,0xec,0x12,0x70,0x80,0x2e,0x71,0x8d,0x3d,0x7,0x9b,0xc4,0x57,0xc6,0x30,0x89,0xaf,0x58,0x24,0xfe,0xe7,0xc0,0xdc,0x44,0xe,0x0,0x0,0xa0,0xe1,0x15,0x49,0x2,0x9f,0xab,0x0,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xba,0x84,0x14,0xff,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xcb,0xd9,0xac,0x43,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0xc,0x8,0x6,0x0,0x0,0x0,0x56,0x75,0x5c,0xe7,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x6c,0x49,0x44,0x41,0x54,0x28,0x91,0x63,0x60,0xa0,0x35,0x60,0x44,0xe6,0x3c,0x78,0xf0,0xe0,0x3f,0x8c,0xfd,0xff,0xff,0xff,0x44,0x45,0x45,0xc5,0x5,0xe8,0x1a,0x98,0x70,0x9a,0xc4,0xc8,0x38,0xe5,0xe1,0xc3,0x87,0xda,0x44,0x6b,0x60,0x60,0x60,0xe0,0xfe,0xff,0xff,0xff,0xaa,0x17,0x2f,0x5e,0x70,0x13,0xab,0x81,0x81,0x81,0x81,0x41,0xeb,0xe7,0xcf,0x9f,0x53,0x48,0xd1,0x80,0x1,0x8,0x69,0xb8,0xc6,0xce,0xce,0x9e,0x43,0xac,0x86,0xaf,0x8c,0x8c,0x8c,0x61,0x12,0x12,0x12,0x5f,0x89,0xd2,0xf0,0xff,0xff,0xff,0x1c,0x79,0x79,0xf9,0xab,0x84,0x1d,0x49,0x6d,0x0,0x0,0x8f,0x30,0x1e,0x10,0x6e,0x79,0xda,0xf9,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -60,12 +60,12 @@ static const unsigned char checker_bg_png[]={ static const unsigned char close_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x4,0x0,0x0,0x0,0xb5,0xfa,0x37,0xea,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x6c,0x49,0x44,0x41,0x54,0x28,0xcf,0xad,0x90,0xd1,0xa,0x80,0x20,0xc,0x45,0xad,0xa7,0x6b,0xee,0x35,0xb1,0x3f,0xf3,0xbb,0x13,0xc,0xea,0x5f,0x5c,0xf,0x42,0x4d,0x1c,0x14,0xd4,0xde,0xc6,0x39,0xd3,0xdd,0x19,0xf3,0x53,0xd9,0x48,0x5e,0xf6,0xe4,0x6d,0x6c,0x30,0xa,0xd2,0xad,0x90,0x47,0x42,0x11,0xa,0xcd,0x76,0x5,0x63,0x9b,0x16,0xd9,0xb9,0x20,0x9f,0xbc,0x14,0x15,0xb,0x65,0x47,0x56,0x71,0x55,0x90,0xc1,0x60,0x1c,0x12,0x8f,0x5a,0x26,0x1e,0xd4,0x79,0xf9,0x45,0x5d,0x57,0x59,0xd2,0x85,0x36,0x51,0x87,0xfb,0xd0,0xef,0xe,0xf5,0x78,0xea,0x4f,0x75,0x2,0x30,0x98,0x34,0x72,0xa,0x11,0xfb,0xc2,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xba,0x84,0x14,0xff,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xcb,0xd9,0xac,0x43,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9b,0x49,0x44,0x41,0x54,0x38,0x8d,0xcd,0x92,0x31,0xe,0xc2,0x30,0x10,0x4,0x17,0xaa,0x3d,0x67,0xdb,0x58,0xd0,0xd3,0xf0,0xa3,0x7c,0x36,0x3c,0x82,0x48,0x44,0x22,0x6f,0xb1,0x4d,0x85,0x14,0x81,0xf,0x2c,0x28,0xe0,0xda,0xd5,0x8c,0x4e,0x77,0xb,0xfc,0xd5,0x98,0xd9,0x20,0x29,0x7a,0xb9,0xa4,0x68,0x66,0x83,0xb,0x93,0xcc,0x24,0xa7,0x9a,0x44,0x52,0x24,0x39,0x91,0xcc,0x55,0x89,0xa4,0xde,0xcc,0xce,0x24,0xb,0xc9,0x39,0x84,0xb0,0xf7,0xb2,0xae,0xeb,0x76,0xde,0x8a,0x4f,0x92,0x66,0xd8,0x91,0x5c,0x49,0x5e,0x9a,0xe1,0xb5,0x64,0x5,0x16,0x92,0x8b,0x7,0x6f,0x9b,0x8c,0x0,0x4a,0x29,0x9b,0x26,0x81,0xa4,0x3e,0xa5,0x34,0x2,0x38,0x2,0x58,0x0,0xcc,0x0,0xe,0x39,0xe7,0xd3,0xfa,0xb0,0xee,0xea,0x8f,0x7,0x7b,0xf5,0x9d,0xb7,0xb0,0x97,0x55,0x25,0x5f,0x17,0xe9,0x2e,0xf9,0xb8,0xca,0x3f,0x9b,0x1b,0x1a,0xe3,0x40,0x47,0xa0,0xda,0xda,0x61,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char close_hl_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x4,0x0,0x0,0x0,0xb5,0xfa,0x37,0xea,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x6c,0x49,0x44,0x41,0x54,0x28,0xcf,0xad,0x90,0xd1,0xa,0x80,0x20,0xc,0x45,0xad,0xa7,0x6b,0xee,0x35,0xb1,0x3f,0xf3,0xbb,0x13,0xc,0xea,0x5f,0x5c,0xf,0x42,0x4d,0x1c,0x14,0xd4,0xde,0xc6,0x39,0xd3,0xdd,0x19,0xf3,0x53,0xd9,0x48,0x5e,0xf6,0xe4,0x6d,0x6c,0x30,0xa,0xd2,0xad,0x90,0x47,0x42,0x11,0xa,0xcd,0x76,0x5,0x63,0x9b,0x16,0xd9,0xb9,0x20,0x9f,0xbc,0x14,0x15,0xb,0x65,0x47,0x56,0x71,0x55,0x90,0xc1,0x60,0x1c,0x12,0x8f,0x5a,0x26,0x1e,0xd4,0x79,0xf9,0x45,0x5d,0x57,0x59,0xd2,0x85,0x36,0x51,0x87,0xfb,0xd0,0xef,0xe,0xf5,0x78,0xea,0x4f,0x75,0x2,0x30,0x98,0x34,0x72,0xa,0x11,0xfb,0xc2,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xba,0x84,0x14,0xff,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xcb,0xd9,0xac,0x43,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9b,0x49,0x44,0x41,0x54,0x38,0x8d,0xcd,0x92,0x31,0xe,0xc2,0x30,0x10,0x4,0x17,0xaa,0x3d,0x67,0xdb,0x58,0xd0,0xd3,0xf0,0xa3,0x7c,0x36,0x3c,0x82,0x48,0x44,0x22,0x6f,0xb1,0x4d,0x85,0x14,0x81,0xf,0x2c,0x28,0xe0,0xda,0xd5,0x8c,0x4e,0x77,0xb,0xfc,0xd5,0x98,0xd9,0x20,0x29,0x7a,0xb9,0xa4,0x68,0x66,0x83,0xb,0x93,0xcc,0x24,0xa7,0x9a,0x44,0x52,0x24,0x39,0x91,0xcc,0x55,0x89,0xa4,0xde,0xcc,0xce,0x24,0xb,0xc9,0x39,0x84,0xb0,0xf7,0xb2,0xae,0xeb,0x76,0xde,0x8a,0x4f,0x92,0x66,0xd8,0x91,0x5c,0x49,0x5e,0x9a,0xe1,0xb5,0x64,0x5,0x16,0x92,0x8b,0x7,0x6f,0x9b,0x8c,0x0,0x4a,0x29,0x9b,0x26,0x81,0xa4,0x3e,0xa5,0x34,0x2,0x38,0x2,0x58,0x0,0xcc,0x0,0xe,0x39,0xe7,0xd3,0xfa,0xb0,0xee,0xea,0x8f,0x7,0x7b,0xf5,0x9d,0xb7,0xb0,0x97,0x55,0x25,0x5f,0x17,0xe9,0x2e,0xf9,0xb8,0xca,0x3f,0x9b,0x1b,0x1a,0xe3,0x40,0x47,0xa0,0xda,0xda,0x61,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -100,12 +100,27 @@ static const unsigned char full_panel_bg_png[]={ static const unsigned char graph_node_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x3,0x0,0x0,0x0,0x24,0xa3,0x7,0xa4,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x1,0x4d,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf,0xd,0x10,0x17,0x14,0x18,0x0,0x0,0x0,0x0,0x0,0x0,0x12,0x10,0x13,0x0,0x0,0x0,0x19,0x17,0x1b,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x16,0x12,0x19,0x0,0x0,0x0,0xe,0xb,0x10,0x0,0x0,0x0,0x0,0x0,0x0,0xe,0xb,0x10,0x16,0x12,0x19,0x0,0x0,0x0,0x1d,0x1a,0x1f,0x35,0x2f,0x38,0xba,0xa9,0xc3,0xc3,0xb7,0xcb,0xbd,0xad,0xc5,0xb9,0xa9,0xc3,0xb5,0xa3,0xbf,0xb4,0xa1,0xbe,0xb4,0xa2,0xbd,0xb4,0xa2,0xbe,0xb3,0xa2,0xbe,0xb1,0xa0,0xbc,0xb2,0xa0,0xbc,0xb2,0x9f,0xbc,0xb0,0x9e,0xba,0xb0,0x9d,0xbb,0xb1,0x9e,0xbb,0xb0,0x9e,0xbb,0xb1,0x9e,0xba,0xaf,0x9c,0xb9,0xae,0x9c,0xb9,0xae,0x9c,0xb8,0xaf,0x9d,0xb9,0xad,0x9b,0xb7,0xad,0x9a,0xb7,0xad,0x9a,0xb8,0xac,0x99,0xb6,0xab,0x99,0xb6,0xac,0x98,0xb6,0xab,0x98,0xb6,0xab,0x99,0xb5,0xa9,0x97,0xb4,0xa9,0x97,0xb5,0xaa,0x97,0xb4,0xa8,0x95,0xb3,0xa8,0x95,0xb2,0xa7,0x95,0xb3,0xa7,0x93,0xb1,0xa6,0x93,0xb1,0xa5,0x91,0xaf,0xa5,0x91,0xb0,0xa4,0x91,0xaf,0xa5,0x92,0xb0,0xa4,0x91,0xb0,0xa5,0x92,0xaf,0xa3,0x90,0xae,0xa3,0x90,0xad,0xa3,0x8f,0xae,0xa2,0x90,0xae,0xa1,0x8e,0xac,0xa1,0x8e,0xad,0xa2,0x8e,0xac,0x9f,0x8d,0xab,0xa0,0x8d,0xab,0xa0,0x8c,0xab,0xa0,0x8d,0xaa,0x9f,0x8c,0xaa,0x9f,0x8c,0xab,0x9e,0x8a,0xaa,0x9e,0x8b,0xa9,0x9e,0x8b,0xaa,0x9e,0x8a,0xa9,0x9d,0x8a,0xa9,0x9c,0x88,0xa7,0x9c,0x88,0xa8,0x9c,0x89,0xa7,0x9c,0x89,0xa8,0x9a,0x87,0xa6,0x9b,0x87,0xa6,0x9b,0x86,0xa6,0x9b,0x87,0xa7,0x19,0x15,0x1c,0x4a,0x42,0x4f,0x3b,0x34,0x3f,0x39,0x30,0x3f,0x24,0x1e,0x27,0xff,0xff,0xff,0x8f,0x6b,0x6d,0x0,0x0,0x0,0x0,0x22,0x74,0x52,0x4e,0x53,0x0,0x1,0x3,0x6,0x8,0x9,0x2,0xc,0x1e,0x33,0x41,0x46,0xd,0x31,0x9a,0xe3,0x5,0x24,0xb4,0x39,0xf4,0x44,0xa,0x47,0x45,0x3d,0xf8,0x2a,0xcd,0x11,0x3f,0xd3,0xfd,0x2b,0x85,0xa8,0x7,0x57,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x6e,0x22,0xf,0x51,0x17,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x1,0x53,0x49,0x44,0x41,0x54,0x38,0xcb,0xed,0xd4,0x69,0x57,0x1,0x51,0x18,0xc0,0xf1,0x8b,0x99,0xb1,0x8c,0x65,0x6c,0x63,0x9d,0xc1,0x10,0xd1,0xc4,0x44,0x23,0x6b,0xb2,0x55,0xa8,0x24,0x92,0xb2,0x15,0x45,0x8a,0xef,0xff,0xb6,0x6b,0xba,0x39,0x4e,0xbd,0xe8,0xb,0xf8,0x9f,0xe7,0xdc,0x73,0x9e,0xdf,0xfb,0xe7,0x2,0x0,0x64,0x72,0x5,0x86,0xc3,0x30,0x85,0x5c,0x6,0x60,0x84,0x52,0xa5,0xd6,0x90,0x30,0x8d,0x5a,0xa5,0x24,0xe0,0xae,0xd5,0xe9,0xd,0x9c,0x94,0x41,0xaf,0xd3,0x12,0x80,0x32,0x9a,0xfc,0x81,0x3d,0xa9,0x80,0xdf,0x64,0xa4,0x0,0x66,0xb6,0x4,0x43,0xfb,0x52,0xa1,0xa0,0xc5,0x8c,0x1,0xdc,0xca,0x85,0x23,0x7,0x61,0x9e,0xe7,0x23,0x3c,0xcf,0x59,0x71,0x40,0xdb,0xb8,0xc3,0x68,0x34,0x1a,0x83,0x13,0x8b,0x71,0x36,0x1a,0xe0,0x24,0x27,0x1c,0x9,0x71,0x21,0x9e,0x48,0x8,0xc7,0x8,0xc4,0xe4,0x49,0x4a,0x4c,0x8a,0x29,0x51,0x44,0x90,0xce,0x64,0xd2,0xe9,0x2c,0x9c,0x2c,0x82,0x5c,0x3e,0x97,0x3b,0xcd,0x17,0xf2,0x67,0x5,0x4,0x45,0x58,0xa9,0x5c,0x2a,0x96,0xcb,0x8,0x2a,0xd5,0x6a,0x65,0xdd,0x79,0x5,0xc1,0xc5,0xe5,0xba,0xf5,0x8b,0xa0,0x56,0x6f,0xd4,0xae,0x1a,0x8d,0xfa,0xf5,0xd,0x82,0xe6,0x6d,0xb3,0xd9,0x6a,0xc1,0xb9,0x43,0xd0,0x6e,0x77,0xee,0xdb,0xb0,0x4e,0x1b,0x41,0xf7,0xa1,0xf7,0xf8,0xd4,0xef,0xf6,0x7b,0x7d,0x4,0x83,0xe1,0x68,0x38,0x1c,0xd,0xc6,0xe3,0x67,0x4,0x2f,0x93,0xe9,0x74,0x3a,0x81,0xbd,0x22,0x78,0x9b,0xc1,0xe6,0xf3,0xd9,0xec,0x1d,0xc1,0x56,0x12,0x2c,0x3e,0x36,0x2d,0xbe,0xe1,0x73,0xd3,0xe,0x76,0xf0,0x1f,0xd0,0xb6,0xdf,0x60,0xdf,0x6,0x3b,0xd,0x30,0x87,0x73,0xf9,0xb3,0x2f,0x9d,0xe,0xc,0x50,0x2e,0xf7,0xa,0xc9,0x72,0xe5,0x76,0x51,0x80,0x60,0x58,0x8f,0x77,0x21,0xe5,0xf5,0xb0,0xc,0xbc,0x75,0x39,0xe3,0x63,0x49,0x1b,0x8c,0x64,0x7d,0x8c,0x5c,0xfa,0xd,0x14,0x38,0x2d,0x85,0x2b,0x8,0xf0,0xb7,0x2f,0x56,0x15,0x7,0x92,0x8b,0x88,0xb4,0x10,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x13,0x7d,0xf7,0x96,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x8,0x17,0xd,0x5,0x12,0xa1,0x38,0x83,0x9b,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x2,0x74,0x49,0x44,0x41,0x54,0x58,0xc3,0xed,0x97,0x3d,0x6f,0xd3,0x60,0x10,0xc7,0x7f,0x17,0x9b,0x26,0x25,0x22,0xad,0xa,0x8,0xf1,0x52,0x75,0x0,0x16,0x24,0x90,0x2a,0x96,0x7c,0x1,0x6,0xc4,0xce,0xc4,0x17,0x0,0x31,0xb0,0x30,0x0,0x23,0x82,0x85,0x5,0x9,0x4,0x5f,0x80,0x89,0x1d,0x31,0xf0,0x5,0x58,0x50,0x25,0x50,0x59,0x80,0xa1,0xe2,0xad,0x28,0x34,0x4a,0x3,0x25,0x76,0xea,0xe7,0x39,0x6,0x3f,0x76,0x6d,0xc7,0x49,0x5f,0xd8,0x90,0x6f,0xb1,0xf5,0xe4,0xb9,0xdf,0xdd,0xfd,0xef,0x22,0xf9,0x84,0x2d,0x13,0xa0,0x6,0x78,0xee,0x29,0xe4,0x4d,0x1,0xb,0x18,0xf7,0x54,0x32,0x97,0x6a,0xc0,0x7e,0x60,0xe,0x38,0xc,0xb4,0x80,0x7d,0x5,0xc0,0x26,0xd0,0x7,0x3a,0x40,0x17,0xf8,0x3,0xd8,0x24,0x6a,0x13,0x38,0x35,0x73,0x60,0xf6,0x6a,0xa3,0xde,0xb8,0x38,0x35,0x55,0x3f,0x41,0x89,0xd,0x87,0xe1,0x97,0x20,0xc,0x5e,0xae,0xff,0xea,0x3d,0x5,0x3e,0x2,0x1b,0xe2,0x22,0x2d,0xcc,0xcd,0x1e,0x7c,0x78,0x72,0xe1,0xf4,0xa5,0x7b,0xb7,0x1f,0x7c,0x9e,0x6e,0x35,0xca,0xfc,0x19,0xf4,0x3,0xee,0xdc,0xbf,0x39,0xff,0x69,0xe5,0xc3,0x8b,0x6e,0x6f,0xed,0x6,0xb0,0x22,0x40,0x3,0x58,0x3c,0x7a,0xe4,0xf8,0xab,0x67,0x4f,0x9e,0x77,0xa3,0xc8,0x12,0xd,0xa3,0x52,0x80,0x3f,0xe5,0xe3,0xfb,0x35,0xae,0x5c,0xbb,0x3c,0xf7,0xfd,0xc7,0xd7,0xb,0xc0,0x92,0xef,0x74,0x68,0xfa,0x9e,0xdf,0x1c,0xfc,0xe,0xbb,0x88,0xc6,0x47,0xa,0x2a,0x59,0x85,0x95,0x61,0xb8,0xc9,0x30,0x4,0xdf,0xf3,0x9b,0xae,0x6c,0x49,0x0,0x1e,0x80,0x51,0x1b,0xfb,0xc7,0x2,0xc7,0x5a,0x3b,0x88,0x66,0xcf,0x63,0xf3,0x12,0x80,0x26,0xbf,0xa8,0xb5,0xa8,0xa,0x88,0x22,0x8,0x8a,0x22,0x2a,0x19,0x37,0x1d,0xe9,0xad,0x9f,0x6b,0xb4,0x55,0x14,0x5,0x55,0x44,0xe2,0x32,0x6c,0xe2,0x24,0x71,0x18,0x9d,0x4,0xb0,0x6a,0xd3,0x1b,0x2a,0xe9,0x4b,0xfc,0xae,0xe4,0x45,0x19,0x9f,0x81,0x2b,0xdb,0x15,0xa6,0xa2,0x19,0x2d,0xec,0x8,0x24,0x7,0x30,0xd6,0x16,0xf8,0x82,0xa8,0xc6,0x45,0x68,0x52,0xbf,0x4e,0xce,0x60,0xeb,0x42,0x5c,0xb4,0x66,0x9c,0x6c,0xc9,0x1f,0xa4,0x0,0xb0,0x39,0xc5,0xc9,0xa1,0x28,0x89,0x5f,0x14,0xd1,0x5a,0x37,0x32,0x89,0xf2,0x82,0xc6,0x3,0xe0,0xda,0xa,0x22,0x3a,0xa9,0xb,0x9a,0x26,0xaa,0xf1,0x41,0x9a,0x42,0x2,0xb2,0xb2,0x6d,0x6,0x5b,0xa3,0xab,0x23,0xd5,0x48,0x32,0x92,0xe3,0x33,0x10,0x37,0xb7,0x2a,0xea,0xee,0x4a,0x2a,0x42,0xe,0x5a,0x2a,0xa2,0x51,0x37,0x40,0x85,0x48,0x96,0xb4,0x23,0xdb,0x88,0x68,0x5c,0xc4,0xcc,0x3c,0x14,0xa7,0x6f,0xa2,0x6,0xaa,0xb1,0x7c,0xd9,0x30,0xaa,0x79,0xc7,0x49,0x93,0x78,0xf7,0xd1,0xad,0x79,0x76,0x69,0x29,0x20,0xda,0x34,0x2c,0x9e,0x3d,0xff,0x7a,0x27,0x4e,0x4b,0xef,0xde,0xb4,0x4b,0x33,0x58,0xef,0xf7,0x76,0x9b,0x0,0x35,0xfe,0xd1,0x2a,0x40,0x5,0xa8,0x0,0x15,0xa0,0x2,0x54,0x80,0xa,0xf0,0x5f,0x2,0xa4,0xe4,0x13,0x78,0xd7,0x19,0xd8,0x3d,0xf8,0xda,0x4,0x60,0x81,0xc0,0x18,0x13,0xda,0x68,0x7,0x5e,0x11,0x18,0x63,0x42,0x20,0x0,0x6c,0xcd,0xad,0xb2,0x6b,0x41,0x38,0x58,0xee,0x74,0x57,0xdb,0x93,0x20,0x36,0x82,0x4e,0x77,0xb5,0x1d,0x84,0x83,0x65,0x60,0xd,0x30,0xc9,0xe6,0x3a,0x3,0x9c,0x6b,0x35,0x67,0x1f,0x37,0xea,0xd3,0x67,0x3c,0xcf,0x2b,0x15,0xd7,0x18,0x63,0x83,0x70,0xf0,0xbe,0xbf,0xd1,0xbb,0xe,0xbc,0x5,0xd6,0x25,0xb3,0xc2,0xb5,0x80,0x63,0xc0,0x21,0xa0,0x3e,0x66,0xf9,0xe,0x81,0x9f,0xc0,0x37,0xb7,0x47,0x1b,0x29,0x8,0xea,0x27,0xfb,0xe0,0x98,0x2a,0xd4,0x95,0x1c,0xed,0x51,0xf8,0x51,0xfb,0xb,0x1,0xbe,0x20,0x9f,0x90,0x81,0x17,0xaa,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +}; + + +static const unsigned char graph_node_breakpoint_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x13,0x7d,0xf7,0x96,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x8,0x6,0xf,0x3b,0x1c,0xec,0x64,0x51,0x75,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x8f,0x49,0x44,0x41,0x54,0x58,0xc3,0xed,0xd7,0xbd,0x9,0xc0,0x20,0x10,0x5,0xe0,0x53,0x2c,0x5d,0x40,0x74,0x4,0xf7,0x9f,0xc4,0x11,0x22,0x2e,0x60,0x6f,0x9a,0x13,0x4e,0x21,0x41,0x50,0x48,0x91,0x77,0x95,0xf8,0xf3,0x79,0x62,0xf5,0x88,0x36,0x4b,0xf5,0x41,0x2d,0xf1,0x22,0x22,0xbf,0x78,0x2e,0x5b,0x97,0x2,0xc9,0xc3,0xc,0x2c,0x95,0xdc,0x6f,0x78,0xce,0x5b,0x97,0xd4,0x42,0x27,0xd9,0xba,0x14,0xac,0x4b,0xa1,0x96,0xd8,0x24,0x20,0x9f,0x41,0x1d,0x7b,0xba,0x59,0xb6,0xaf,0xa7,0x3d,0x7e,0x78,0xdb,0x54,0xbc,0x36,0x74,0xa7,0x77,0x7f,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7e,0x4,0xe4,0xb7,0xfc,0xc8,0x6b,0x59,0xce,0x99,0x39,0x95,0x71,0xb4,0x6b,0x4b,0x89,0xf5,0x44,0x72,0x3d,0x93,0x9d,0x3f,0xad,0x1b,0x54,0xed,0x49,0xd3,0x36,0x45,0x4f,0x1f,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char graph_node_close_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0xc,0x8,0x4,0x0,0x0,0x0,0xfc,0x7c,0x94,0x6c,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x65,0x49,0x44,0x41,0x54,0x18,0xd3,0x75,0x90,0x4b,0xe,0x80,0x20,0xc,0x44,0x47,0x57,0x53,0x64,0x2b,0x91,0x9b,0x71,0x6e,0x49,0x30,0xd1,0xbb,0x80,0xb,0xa2,0xb6,0x26,0x74,0x37,0x9f,0x34,0xaf,0x5,0x20,0xc9,0x7,0xa8,0xf1,0x41,0x12,0x0,0x49,0xac,0xcc,0x5f,0xe4,0x3,0x33,0xab,0x24,0xf8,0x55,0x76,0x36,0x1e,0x2e,0x2,0x78,0xd5,0xb2,0x29,0xe1,0xa2,0xb1,0x55,0xef,0x64,0x31,0x76,0x8f,0x58,0xd8,0xd8,0x78,0x3d,0xf6,0x8c,0xdf,0xb4,0xc9,0xf4,0xf5,0xaa,0x8e,0x61,0x48,0xc,0xa1,0x25,0x51,0xd1,0xf0,0xc0,0xd1,0x4b,0x6e,0xc7,0xae,0x34,0x72,0x3,0xf5,0x60,0xdd,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xba,0x84,0x14,0xff,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xcb,0xd9,0xac,0x43,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0xc,0x8,0x6,0x0,0x0,0x0,0x56,0x75,0x5c,0xe7,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x93,0x49,0x44,0x41,0x54,0x28,0x91,0x95,0x92,0x31,0xe,0xc2,0x30,0x10,0x4,0x17,0xaa,0x3d,0x7b,0xdb,0x58,0xa4,0xa7,0xe1,0x47,0xfe,0x2c,0x3c,0x82,0x48,0x44,0x22,0x6f,0xb1,0x4d,0x15,0xc9,0x20,0x1f,0x52,0xae,0xdd,0xd9,0x2b,0xe6,0xe,0x0,0x60,0x66,0x59,0x52,0x82,0x33,0x92,0x92,0x99,0x65,0xec,0x30,0xc9,0x4a,0x72,0x19,0x95,0x24,0x25,0x92,0xb,0xc9,0x6a,0x66,0x19,0x92,0x26,0x33,0x7b,0x92,0x6c,0x24,0xd7,0x10,0xc2,0xdc,0xc1,0x5f,0x59,0x8c,0xf1,0x32,0xc,0x42,0x8,0xb3,0xb,0x3b,0xdb,0xde,0x24,0x5f,0x2e,0xdc,0x97,0x3a,0xb0,0x91,0xdc,0x7e,0xe1,0xb3,0x67,0x66,0x9f,0xd6,0xda,0x69,0x58,0x90,0x34,0x95,0x52,0xee,0x0,0x6e,0x0,0x36,0x0,0x2b,0x80,0x6b,0xad,0xf5,0xd1,0x8b,0x70,0x6d,0xb8,0xf6,0xfe,0xd9,0x18,0x96,0xe,0x1f,0xe,0x38,0xf6,0x1a,0x1f,0x9f,0xec,0x40,0x47,0x56,0x51,0x84,0x77,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +}; + + +static const unsigned char graph_node_comment_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x13,0x7d,0xf7,0x96,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x8,0x19,0x11,0x2a,0x1d,0xd6,0x78,0x8b,0x40,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x74,0x49,0x44,0x41,0x54,0x58,0xc3,0xed,0x97,0xbf,0x4e,0xc2,0x50,0x14,0xc6,0x7f,0x6d,0x91,0x56,0x1b,0x90,0x80,0x2c,0x44,0xc2,0xa0,0x2e,0xe,0x3e,0x3,0x89,0x93,0xf1,0x1d,0x4c,0x18,0x4d,0x1c,0x7c,0xb,0x57,0x7,0x13,0x47,0x13,0x77,0x46,0xe3,0xc4,0x4b,0x98,0x60,0x4c,0xd4,0x81,0x60,0x58,0x94,0xff,0x22,0x2d,0xd0,0xd6,0xe5,0xde,0x88,0x8,0x2,0x35,0x6e,0xf7,0x5b,0x6e,0x9a,0x9c,0xef,0x77,0xee,0x39,0x37,0x1d,0x3e,0x8d,0x2f,0x69,0x80,0xe,0x18,0xe2,0xd4,0xf8,0xae,0x0,0xf0,0x1,0x4f,0x9c,0x1,0x63,0x45,0x3a,0xb0,0x6,0x24,0x81,0x34,0x10,0x7,0x56,0x26,0x0,0x43,0xa0,0x3,0xbc,0x2,0xd,0xe0,0x3,0xf0,0x65,0x57,0x1b,0xd8,0x5e,0x8f,0x25,0x8e,0x2d,0xd3,0x3a,0x88,0x46,0xcd,0x4d,0xa6,0x68,0x30,0x70,0x5f,0x1c,0xd7,0xb9,0x6d,0x77,0x5b,0x97,0xc0,0x13,0xd0,0xd3,0x44,0xa7,0x5c,0x32,0x91,0x3a,0xdf,0xca,0xed,0x1c,0x16,0x52,0xdd,0x2a,0xbf,0xe8,0xaa,0x1e,0xcb,0x3e,0x57,0x1e,0x6f,0x1a,0xad,0xfa,0x29,0x50,0x91,0x33,0xa7,0x4d,0xd3,0xca,0xcf,0x33,0x3,0x14,0x52,0xdd,0xaa,0x69,0x5a,0x79,0x31,0xaa,0x21,0x97,0x65,0x47,0x8c,0x88,0xcd,0x82,0x12,0xb5,0x36,0xa0,0x49,0x80,0xc1,0xf2,0x32,0x24,0x20,0x90,0x4f,0x12,0x46,0x3a,0x7f,0x94,0x2,0x28,0x80,0x2,0x88,0x5f,0x7b,0xfc,0xe3,0xec,0xe1,0x3d,0x1b,0x1a,0x30,0x1a,0x7a,0x1c,0x65,0xd8,0x5f,0xc4,0x74,0x5d,0xa3,0xa4,0x5e,0x41,0x1,0x14,0x40,0x1,0x14,0x40,0x1,0x14,0x40,0x1,0xfe,0x15,0xa0,0x4d,0xc9,0x88,0x4b,0xdf,0xc0,0xf,0xe1,0xf5,0x25,0xc0,0x7,0x1c,0xcf,0xf3,0xdc,0x45,0x9d,0xa2,0xd6,0x1,0x7c,0x5d,0x44,0xd9,0xba,0xe3,0xf6,0xcb,0xc5,0xa6,0x5d,0x9a,0x67,0x2e,0x36,0xed,0x92,0xe3,0xf6,0xcb,0x40,0x1d,0xf0,0x64,0x72,0x5d,0x7,0xf6,0xe2,0x76,0xe2,0xc2,0x32,0x57,0x77,0xd,0xc3,0xd0,0x67,0x74,0xf6,0x1d,0xb7,0x7f,0xdf,0xe9,0xb5,0x4e,0x80,0x3b,0xa0,0xad,0x8d,0x45,0xb8,0x38,0x90,0x1,0x36,0x0,0x73,0x46,0xf8,0x76,0x81,0x37,0xa0,0x26,0x72,0xb4,0xa7,0x4d,0x2c,0x34,0x22,0xf3,0xe0,0x8c,0x9,0x2,0x31,0xf2,0x28,0xe4,0xe2,0x7f,0xea,0x13,0x64,0x47,0x6c,0x83,0x36,0x6d,0xd2,0x40,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +}; + + +static const unsigned char graph_node_comment_focus_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x13,0x7d,0xf7,0x96,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x0,0x0,0x0,0x0,0x0,0xf9,0x43,0xbb,0x7f,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x9,0x2,0xe,0x16,0x22,0xbe,0xef,0xc2,0xe1,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x4a,0x49,0x44,0x41,0x54,0x58,0xc3,0xed,0xd7,0xbf,0x4b,0xdb,0x41,0x1c,0xc6,0xf1,0xd7,0x37,0x51,0x4,0x3,0xa,0xa2,0x20,0xd2,0xe2,0xe2,0x64,0x41,0xdc,0xdc,0xac,0xe0,0x54,0xdc,0xb2,0xe6,0x2f,0x10,0x1a,0xf0,0x4f,0x11,0x22,0xf8,0x17,0x64,0xcd,0x26,0x9d,0x1c,0x74,0x73,0x13,0x21,0x4e,0x2e,0xa5,0xa5,0x14,0xac,0x82,0x82,0x62,0xd0,0x7c,0xd3,0xa1,0x77,0x18,0x35,0xfe,0x48,0xa4,0xdb,0x3d,0x70,0xdc,0xf2,0x79,0xde,0x77,0xf7,0x39,0x38,0xee,0xc9,0xdc,0x2b,0x43,0x1,0xc5,0x30,0x67,0x1e,0xaa,0x83,0x1c,0xed,0x30,0x77,0x74,0x15,0x15,0x30,0x8a,0x9,0x4c,0x61,0xc,0xc3,0x8f,0x0,0xb7,0xb8,0xc4,0x29,0xce,0x71,0x8d,0x3c,0xae,0x5a,0xc2,0x5c,0xa3,0x5a,0x59,0xc7,0x17,0x7c,0xd0,0x5b,0x3f,0xf1,0xad,0x5c,0xab,0x6f,0xe3,0x4,0x57,0x59,0x58,0x69,0xb6,0x51,0xad,0x6c,0x62,0xed,0x77,0xf3,0xf0,0x87,0x17,0x34,0xfd,0x69,0xf1,0x23,0x76,0xca,0xb5,0xfa,0x6,0xbe,0xc7,0x33,0x4f,0x61,0xe5,0x35,0x33,0x84,0x9a,0x95,0xe0,0x29,0xc6,0x66,0x95,0xc2,0x78,0xab,0x62,0x7d,0x16,0x1,0x45,0xfd,0xab,0x18,0x1,0x9d,0x78,0x25,0x83,0xa8,0xe0,0x9d,0x4a,0x80,0x4,0x48,0x80,0x7f,0x1a,0xea,0xf1,0xda,0xc,0xe,0x38,0xd8,0xdf,0x5b,0x7d,0x8b,0x69,0x69,0xf9,0xf3,0x6e,0xba,0x85,0x4,0x48,0x80,0x4,0x48,0x80,0x4,0x48,0x80,0x4,0xf8,0xaf,0x80,0xac,0x47,0x46,0xec,0x7b,0x7,0xf9,0x0,0xde,0x3c,0x2,0x72,0xdc,0xa0,0xd5,0x87,0xb9,0x15,0x3c,0x79,0x21,0x44,0xd9,0x33,0x34,0xbb,0x3f,0x4f,0xaf,0x7c,0xb0,0x9a,0xc1,0xd3,0x8e,0xc9,0x75,0x1c,0xb,0x8d,0x6a,0x65,0xb,0xf3,0x2f,0x34,0x37,0xc7,0x71,0xb9,0x56,0xff,0x8a,0x23,0x5c,0x64,0x5d,0x11,0x6e,0xc,0x33,0x98,0xc4,0xc8,0x33,0xe1,0xbb,0x85,0x3f,0xf8,0x15,0x72,0x74,0x3b,0x7b,0xd4,0xd0,0xa1,0x98,0x7,0x9f,0xd9,0x41,0x27,0x1c,0xf9,0x6e,0xc0,0xc6,0x3f,0xd5,0x5f,0x9d,0x54,0x4e,0x15,0xfd,0xeb,0xb4,0x4f,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -119,13 +134,18 @@ static const unsigned char graph_node_default_focus_png[]={ }; +static const unsigned char graph_node_position_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x13,0x7d,0xf7,0x96,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x8,0x6,0xf,0x3b,0x3b,0x49,0x6e,0xe4,0x1e,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x90,0x49,0x44,0x41,0x54,0x58,0xc3,0xed,0xd7,0xbd,0x9,0xc0,0x20,0x10,0x5,0xe0,0x53,0x2c,0xdd,0x40,0x47,0x70,0x7,0x67,0x77,0x7,0x47,0x88,0x1b,0xd8,0x9b,0xe6,0x84,0x53,0x48,0x10,0x14,0x52,0xe4,0x5d,0x25,0xfe,0x7c,0x9e,0x58,0x3d,0xa2,0xcd,0x52,0x7d,0x50,0x63,0xb8,0x88,0xc8,0x2d,0x9e,0x2b,0x36,0x65,0x4f,0xf2,0x30,0x3,0x4b,0x25,0xf7,0x1b,0x9e,0x73,0x36,0x65,0xb5,0xd0,0x49,0xb1,0x29,0x7b,0x9b,0xb2,0xaf,0x31,0x34,0x9,0xc8,0x67,0x50,0xc7,0x9e,0x6e,0x96,0xed,0xeb,0x69,0x8f,0x1b,0xde,0x36,0x15,0xaf,0xd,0xdd,0xe9,0xdd,0x5f,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0x1f,0x1,0xe5,0x2d,0x3f,0xf2,0x5a,0x91,0x73,0x66,0x4e,0x65,0x1c,0xed,0xda,0x52,0x62,0x3d,0x91,0x5c,0xcf,0x64,0xe7,0x4f,0xeb,0x6,0x80,0xff,0x44,0x93,0xd4,0xd9,0xea,0x7e,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +}; + + static const unsigned char graph_node_selected_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x3,0x0,0x0,0x0,0x24,0xa3,0x7,0xa4,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0xd8,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf,0xd,0x10,0x17,0x14,0x18,0x0,0x0,0x0,0x0,0x0,0x0,0x12,0x10,0x13,0x0,0x0,0x0,0x19,0x17,0x1b,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x16,0x12,0x19,0x0,0x0,0x0,0xe,0xb,0x10,0x0,0x0,0x0,0x0,0x0,0x0,0xe,0xb,0x10,0x16,0x12,0x19,0x0,0x0,0x0,0x1d,0x1a,0x1f,0x35,0x2f,0x38,0x94,0xd6,0x84,0xa4,0xdc,0x95,0x99,0xd8,0x8a,0x8c,0xd3,0x7b,0x8b,0xd2,0x79,0x88,0xd1,0x76,0x87,0xd1,0x74,0x86,0xd0,0x73,0x85,0xd0,0x71,0x83,0xcf,0x70,0x82,0xcf,0x6f,0x81,0xce,0x6d,0x7f,0xce,0x6c,0x7b,0xcc,0x67,0x7d,0xcd,0x68,0x7a,0xcc,0x65,0x79,0xcb,0x64,0x76,0xca,0x61,0x75,0xca,0x60,0x78,0xcb,0x62,0x74,0xc9,0x5e,0x72,0xc9,0x5c,0x70,0xc8,0x59,0x71,0xc8,0x5b,0x6d,0xc7,0x57,0x6f,0xc7,0x58,0x6c,0xc6,0x55,0x68,0xc4,0x51,0x67,0xc4,0x4f,0x69,0xc5,0x52,0x19,0x15,0x1c,0x4a,0x42,0x4f,0x3b,0x34,0x3f,0x39,0x30,0x3f,0x24,0x1e,0x27,0xff,0xff,0xff,0x23,0xbb,0x3,0x70,0x0,0x0,0x0,0x22,0x74,0x52,0x4e,0x53,0x0,0x1,0x3,0x6,0x8,0x9,0x2,0xc,0x1e,0x33,0x41,0x46,0xd,0x31,0x9a,0xe3,0x5,0x24,0xb4,0x39,0xf4,0x44,0xa,0x47,0x45,0x3d,0xf8,0x2a,0xcd,0x11,0x3f,0xd3,0xfd,0x2b,0x85,0xa8,0x7,0x57,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x47,0x60,0xbd,0xc9,0x7b,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x4,0x4e,0x1d,0x2,0xaf,0x0,0x0,0x1,0x7,0x49,0x44,0x41,0x54,0x38,0xcb,0xed,0xd4,0xd9,0x5a,0x82,0x40,0x14,0xc0,0xf1,0x23,0x9b,0xb,0x2e,0xb8,0x81,0x1b,0xa8,0x23,0x59,0xb1,0xa4,0x51,0x60,0x81,0x85,0x52,0xf8,0xfe,0x8f,0xd4,0x71,0x3a,0xcd,0xe7,0x57,0x17,0xbd,0x80,0xbf,0x99,0x73,0x71,0xfe,0xf7,0x33,0x0,0x50,0x91,0x64,0x45,0x45,0x8a,0x2c,0x55,0x0,0x69,0xd5,0x5a,0xbd,0xa1,0xa3,0x46,0xbd,0x56,0xd5,0x70,0x6f,0xb6,0xda,0x1d,0xc6,0x75,0xda,0xad,0xa6,0x6,0x46,0xb7,0xb7,0x72,0x6f,0x38,0x77,0xd5,0xeb,0x1a,0xa0,0xf4,0x7,0x6b,0xf7,0x96,0x73,0xd7,0x83,0xbe,0x2,0xea,0x90,0xdd,0x9,0x6c,0xa8,0x82,0x69,0xb1,0x7b,0xe4,0xe1,0xf5,0x3c,0x66,0x99,0xa0,0xea,0xcc,0xf3,0x3d,0x42,0x21,0x8,0x43,0x3f,0x8,0x3,0x3f,0x8,0x28,0x3c,0x8,0x14,0x36,0x68,0x8b,0x67,0xb3,0xa5,0xf0,0x88,0xa2,0x28,0xc2,0xa1,0xf0,0x24,0x50,0x78,0x16,0x28,0xc4,0x71,0x12,0xef,0x92,0x24,0x4e,0x76,0x14,0x5e,0x4,0xa,0xaf,0x2,0x85,0x34,0xcb,0xb2,0x14,0x65,0x29,0x85,0xfd,0xdb,0xd9,0x1e,0x51,0x78,0x17,0x28,0xe4,0x67,0x87,0x43,0x9e,0x1f,0x29,0x5c,0xe0,0xa1,0xf8,0x10,0x8a,0xef,0xf0,0x29,0x5c,0xc3,0x35,0xfc,0x17,0x4c,0xeb,0x77,0x18,0x5d,0x86,0x91,0x9,0xca,0x78,0x52,0xfe,0xec,0xe5,0x64,0xac,0x80,0x31,0x9d,0x9d,0xa8,0x94,0xa7,0xd9,0xd4,0x0,0xcd,0x76,0xe6,0x8b,0x82,0x5b,0xcc,0x1d,0x1b,0xdf,0xba,0x64,0x2f,0x1d,0xdd,0x42,0xba,0xb3,0xb4,0x25,0xfe,0x1b,0xc8,0xaa,0xc9,0xa9,0xb2,0x6,0x7f,0x7d,0x1,0x5d,0xdd,0xb5,0x61,0x26,0xcd,0x71,0x81,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x13,0x7d,0xf7,0x96,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x8,0x17,0xd,0x4,0x3b,0xfa,0x91,0x2a,0xb6,0x0,0x0,0x3,0x44,0x49,0x44,0x41,0x54,0x58,0xc3,0xed,0x97,0x3f,0x68,0xdc,0x76,0x14,0xc7,0xbf,0xef,0xa7,0x9f,0x7e,0x3a,0xdd,0x39,0xf6,0xdd,0x95,0xb3,0x3,0xc1,0x75,0x1b,0x70,0xa,0xe9,0x98,0x25,0x93,0x87,0x52,0x3a,0x4,0x2,0xce,0xe0,0xd2,0x34,0x35,0x94,0x8e,0x1d,0xbc,0xd5,0x4b,0xc7,0x2e,0x25,0x63,0x2,0x5d,0xa,0xa5,0xb1,0x1b,0x2,0xf5,0xd0,0x40,0xa0,0x90,0x10,0x3a,0x64,0xca,0x92,0x31,0x81,0x24,0xd0,0xd2,0x9a,0x40,0x2f,0x17,0xdf,0x1f,0xfb,0x74,0xf2,0xe9,0x27,0xfd,0x5e,0x7,0x49,0xb6,0x4e,0xe7,0xea,0x86,0x6e,0xe5,0x1e,0xdc,0x49,0x42,0xef,0x7d,0xde,0xf7,0x7d,0xf5,0x13,0xe8,0x47,0xcc,0x4c,0x0,0xc4,0xbd,0x7b,0x4f,0x9c,0xb0,0xdd,0x71,0xdb,0xfb,0x2d,0xc7,0xb0,0x11,0x5a,0x7,0x84,0x4c,0xd8,0xb6,0x62,0x41,0xc2,0xd4,0x67,0x1b,0x43,0x59,0xaf,0xf9,0x97,0x2f,0x5f,0x18,0x2,0x30,0xc4,0xcc,0xd6,0xdd,0x1f,0xef,0x9e,0xea,0x79,0x83,0x33,0xed,0x6e,0xf7,0x6c,0xaf,0xd7,0x59,0xe8,0x7b,0xfd,0x72,0x10,0x4,0x32,0xb,0x50,0x4a,0x85,0x33,0x95,0x99,0xc1,0xdc,0x5c,0xad,0x59,0xaf,0x56,0x7f,0x9f,0xab,0x94,0x5f,0xad,0x7e,0xbe,0x7a,0x40,0x5b,0x5b,0xf7,0x2b,0x41,0xbb,0xf9,0x6e,0xa7,0xd7,0x5e,0xb9,0x72,0x75,0xe5,0x86,0x72,0xa4,0x85,0x82,0x8,0x86,0x61,0xf4,0xcb,0x9d,0x47,0x1b,0xb5,0xb9,0xfa,0x23,0x55,0x5f,0xf8,0x43,0xea,0x4e,0xb7,0xdc,0x7c,0xf3,0xfa,0xdc,0xc7,0xeb,0x1f,0xdc,0x64,0x66,0x71,0xb8,0x37,0xbb,0x2b,0x1d,0xb,0x44,0x23,0x13,0x80,0x99,0x11,0xe,0x23,0x50,0x65,0x6f,0x71,0xf5,0x93,0x95,0x9b,0x3f,0x6f,0xff,0xb6,0x76,0x9a,0x9c,0xa6,0x8,0x42,0x5f,0x79,0xfd,0x83,0x79,0xa7,0x24,0x5,0xfc,0xfa,0x2e,0x9,0x42,0xa8,0xd,0xc2,0x20,0x1a,0xfd,0x69,0x3,0x12,0x4,0xf8,0xf5,0x5d,0xa7,0x24,0x85,0xd7,0x3f,0x98,0xf,0x42,0x5f,0x9,0xc3,0x46,0xc,0xfc,0x81,0xb,0x0,0x91,0x66,0x30,0x1b,0x10,0x0,0x98,0x6c,0x7b,0x80,0xc0,0x60,0x66,0x44,0x21,0x3,0x0,0x6,0xfe,0xc0,0x35,0x6c,0x84,0xd0,0x5a,0x53,0x84,0x88,0x0,0x80,0x13,0xd9,0xcc,0xc,0x88,0xb8,0x10,0x0,0x40,0x0,0x1b,0x0,0xcc,0x0,0xc7,0x39,0x11,0x22,0xd2,0x5a,0x93,0xb4,0x6d,0x9b,0x11,0x25,0x89,0x86,0xc1,0x20,0x80,0x18,0xa0,0xe3,0xee,0x47,0xd0,0xcc,0x31,0xad,0x91,0x79,0xa3,0x40,0x4,0x80,0x91,0xe6,0xe5,0x83,0x73,0x37,0x64,0xee,0x2e,0xd8,0x24,0x9,0xc4,0xc7,0xa,0xb2,0x6a,0x8a,0x0,0x1c,0xf7,0xce,0x5e,0xc4,0xc5,0xe6,0x18,0x92,0x57,0x36,0x2,0x30,0x26,0x33,0x7b,0xe2,0x1e,0x71,0xe2,0xb,0x33,0x68,0xf2,0x8,0xd9,0x16,0x94,0xd1,0x13,0xff,0x9b,0x49,0xa,0xc0,0x6,0x6c,0x72,0xf6,0x8f,0xbb,0x58,0xe0,0x41,0x32,0x77,0x22,0x1a,0xc9,0xf2,0x49,0x87,0x89,0xcf,0x8a,0x14,0xc4,0x0,0x93,0x14,0x66,0xba,0xd1,0xf1,0xec,0xa6,0x18,0x60,0xe2,0xfa,0x91,0xde,0xd9,0xae,0x34,0xf9,0x31,0x52,0xba,0x1e,0x28,0x5d,0x4c,0x94,0xfa,0x99,0xbc,0xf,0x45,0xa,0x4c,0x5c,0x38,0xd6,0xc9,0xe0,0xe8,0x89,0xe4,0xad,0x1d,0x5f,0xca,0x9c,0x7f,0x15,0x8b,0x63,0xdc,0xc4,0x7c,0x8f,0x8c,0x91,0xb9,0x93,0x71,0xc0,0xd7,0xdf,0x7c,0xf5,0xea,0xd9,0x8b,0xa7,0x85,0x1d,0xcf,0x9f,0x7b,0x1f,0xdf,0xdf,0xfa,0x76,0xf1,0x44,0xc0,0xd9,0xa5,0x65,0x58,0xc2,0x2e,0x4,0x2c,0x2d,0xbe,0xf3,0xef,0xa,0x3c,0xaf,0x8f,0xde,0x7e,0xb7,0x10,0xe0,0x79,0xfd,0x91,0x6b,0x81,0xff,0x18,0x53,0xc0,0x14,0x30,0x5,0x4c,0x1,0x53,0xc0,0x14,0x30,0x5,0xfc,0xff,0x0,0x5a,0x6b,0x82,0x75,0xe2,0xe7,0xcf,0xc9,0x91,0xe6,0x58,0x19,0x5,0x16,0x2c,0x6,0x0,0x5b,0xca,0x89,0xf5,0x69,0x4e,0x5a,0x23,0x1c,0xe5,0x44,0x8e,0x52,0x1,0x0,0x94,0xdd,0x99,0x89,0x80,0x34,0xc7,0x51,0x2a,0x70,0x94,0x13,0x49,0x25,0xdd,0xa0,0xe4,0x96,0x5b,0xc3,0x43,0xcd,0x1b,0x9b,0x9f,0x5e,0xbc,0x71,0x9d,0x1e,0xf,0xfc,0x3,0xe8,0x30,0x1c,0xd9,0x74,0xd9,0x52,0xa2,0xec,0x9e,0xc2,0xc6,0xe6,0xd5,0x8b,0xc3,0x43,0xcd,0x25,0xb7,0xdc,0x52,0xd2,0xd,0x68,0x6b,0xeb,0x7e,0x65,0xef,0xaf,0x97,0xcb,0xdd,0xfd,0xce,0x87,0x9f,0x7d,0x71,0xe9,0xba,0xe3,0xda,0x85,0x4e,0xc,0x7d,0xcd,0x3f,0xfd,0xf0,0xeb,0x66,0x75,0xb6,0xf6,0xf0,0xad,0xb7,0x97,0x5f,0x12,0x33,0x5b,0xb7,0xbf,0xbb,0x3d,0xdb,0xea,0x74,0x97,0x3a,0xdd,0xee,0x7b,0x3,0xdf,0x9b,0xd7,0x5a,0xdb,0xc6,0x8c,0x7e,0xad,0xa,0x21,0x60,0xdb,0xb6,0x2e,0xbb,0x95,0xd7,0xb5,0x6a,0xf5,0x79,0xa3,0x56,0xfd,0xf3,0xda,0x97,0xd7,0xf6,0x29,0xdd,0xbd,0x6f,0x6f,0x3f,0x28,0xf5,0xff,0x6e,0x56,0xb4,0x19,0x2a,0x66,0x73,0xe2,0xe3,0x25,0x12,0xc6,0x16,0x4e,0x30,0x73,0x7a,0xc1,0x5b,0x5f,0xff,0xe8,0x10,0xc0,0xd1,0xf6,0x4,0xcc,0x4c,0x3b,0x3b,0x3b,0xa2,0xd1,0x68,0x14,0x8e,0xd0,0x6a,0xb5,0x78,0x6d,0x6d,0xcd,0x10,0xc5,0xdb,0xba,0x7f,0x0,0xb2,0x1f,0xaf,0x82,0x62,0x7a,0x69,0xbb,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char graph_port_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xa,0x0,0x0,0x0,0xa,0x8,0x3,0x0,0x0,0x0,0xba,0xec,0x3f,0x8f,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0xc0,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0xff,0xff,0xff,0x6a,0x6a,0x6a,0x52,0x52,0x52,0x61,0x61,0x61,0x48,0x48,0x48,0x94,0x94,0x93,0xca,0xca,0xca,0x94,0x94,0x94,0x92,0x92,0x92,0xbf,0xbf,0xbe,0xbe,0xbf,0xbe,0x92,0x91,0x91,0x50,0x50,0x50,0xc2,0xc1,0xc2,0xc1,0xc1,0xc1,0xc1,0xc1,0xc0,0xc1,0xc2,0xc2,0x50,0x50,0x4f,0x5c,0x5c,0x5c,0x5b,0x5b,0x5b,0x5b,0x5a,0x5a,0x4f,0x4f,0x4f,0xb5,0xb5,0xb5,0xd7,0xd7,0xd7,0x4f,0x4f,0x4e,0x88,0x88,0x88,0xda,0xdb,0xdb,0xda,0xda,0xda,0x45,0x45,0x45,0x86,0x86,0x86,0xac,0xac,0xac,0x4c,0x4d,0x4c,0x55,0x55,0x55,0x56,0x55,0x55,0x4d,0x4e,0x4c,0xda,0xda,0xda,0xd9,0xda,0xda,0xcf,0xd0,0xd0,0xb6,0xb6,0xb6,0xd0,0xd0,0xd0,0xc4,0xc4,0xc4,0xc8,0xc8,0xc8,0xca,0xcb,0xcb,0xc7,0xc7,0xc7,0xcf,0xcf,0xd0,0xd2,0xd2,0xd2,0xd0,0xcf,0xcf,0xca,0xcb,0xca,0xc6,0xc6,0xc5,0xd5,0xd6,0xd5,0xd8,0xd8,0xd8,0xd7,0xd8,0xd8,0xd6,0xd6,0xd6,0xc6,0xc6,0xc6,0xde,0xde,0xde,0xdf,0xdf,0xde,0xdf,0xde,0xdf,0xbc,0xbc,0xbc,0xe8,0xe8,0xe9,0xe8,0xe8,0xe8,0xb7,0xb7,0xb7,0xb6,0xb7,0xb6,0x0,0x0,0x0,0xf5,0xba,0x5d,0x7a,0x0,0x0,0x0,0x24,0x74,0x52,0x4e,0x53,0x0,0x1,0x8,0x5e,0x8c,0x15,0xe2,0xfe,0xe2,0xe2,0xfe,0xfe,0xe2,0x5e,0xfe,0xfe,0xfe,0xfe,0x5e,0x8c,0x8c,0x8c,0x5d,0xfd,0xfe,0x5d,0xe2,0xfe,0xfe,0x16,0xe2,0xfd,0x5d,0x8c,0x8c,0x5d,0xce,0x80,0x8b,0x8f,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x0,0x88,0x5,0x1d,0x48,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x70,0x49,0x44,0x41,0x54,0x8,0xd7,0x15,0xcd,0xb,0x2,0x81,0x50,0x14,0x5,0xc0,0x73,0x6f,0x25,0x84,0x90,0x94,0xa8,0xa4,0x48,0x1f,0xa9,0x1e,0xa2,0x62,0xff,0xcb,0xc2,0x6,0x66,0x0,0x62,0x49,0x96,0x25,0x26,0x80,0x94,0x81,0x1a,0x1d,0xd5,0xa1,0x42,0xe0,0xd1,0x69,0x1c,0xc7,0xda,0x79,0xc2,0x98,0xce,0xf4,0x24,0x4d,0x93,0xf9,0x62,0x9,0x23,0xcb,0x2f,0x45,0x71,0xcd,0x4b,0x3,0xab,0xaa,0x16,0x42,0xdc,0xee,0xf,0x13,0x6b,0xcb,0x6e,0x9e,0xaf,0xc6,0xb6,0x36,0x60,0xa7,0xdd,0x76,0xfd,0xae,0x75,0x18,0xe4,0x7a,0xfe,0xfb,0xe3,0x7b,0xee,0x1f,0xe6,0x7d,0x70,0x8,0x7f,0xc5,0x17,0xe3,0x97,0xa,0x2b,0xff,0x1e,0x73,0x38,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xa,0x0,0x0,0x0,0xa,0x8,0x6,0x0,0x0,0x0,0x8d,0x32,0xcf,0xbd,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0xc6,0x49,0x44,0x41,0x54,0x18,0x95,0x6d,0x90,0x3d,0x4e,0xc4,0x30,0x14,0x84,0xbf,0xb1,0xa8,0x92,0x48,0x39,0x46,0xe2,0x9a,0x9f,0x12,0xc1,0xbd,0x16,0x25,0x4b,0x41,0xb,0x67,0xa1,0xa7,0xa2,0x63,0xa1,0x76,0x94,0x5b,0x58,0x72,0x52,0x3e,0xd3,0xc4,0x11,0xda,0xe5,0xab,0x46,0xa3,0xd1,0x68,0xde,0x13,0x1b,0x21,0x84,0x7,0x49,0x3,0x70,0xbb,0x59,0x5f,0xc0,0x5b,0xdf,0xf7,0xef,0x0,0x2,0x98,0xa6,0xe9,0x0,0x1c,0x1,0xc7,0x19,0x39,0xe7,0x67,0xef,0xfd,0xa0,0xad,0xe9,0x3,0x70,0x6d,0xdb,0x52,0xd7,0x35,0x0,0xcb,0xb2,0x10,0x63,0x4,0x30,0xe7,0xdc,0xe3,0x95,0xa4,0xb1,0x84,0x9a,0xa6,0xd9,0x9b,0x8a,0x8e,0x31,0x3a,0x33,0x1b,0x1d,0x70,0xd,0xec,0x4d,0x7f,0xa9,0xaa,0xaa,0xc8,0x1b,0x7,0xe4,0x8b,0xc4,0x25,0xd9,0x1,0x3f,0x65,0xd3,0x39,0xeb,0xba,0x16,0xf9,0xed,0x80,0xd7,0x6d,0xb,0x29,0x25,0xcc,0xc,0x33,0x23,0xa5,0xb4,0x1f,0x23,0x69,0x14,0x40,0x8,0xe1,0x28,0xe9,0xf0,0xcf,0x7b,0x2c,0xe7,0xfc,0xe4,0xbd,0x7f,0x51,0x71,0xe6,0x79,0xbe,0x37,0xb3,0x1,0xb8,0xdb,0x76,0x9f,0x24,0x8d,0x5d,0xd7,0x7d,0x2,0xfc,0x2,0xfb,0x83,0x50,0x87,0x89,0x31,0xee,0x78,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -165,32 +185,37 @@ static const unsigned char hsplitter_png[]={ static const unsigned char icon_add_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x0,0x0,0x0,0x0,0x3a,0x98,0xa0,0xbd,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x74,0x52,0x4e,0x53,0x0,0x0,0x76,0x93,0xcd,0x38,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x4,0x4e,0x1d,0x2,0xaf,0x0,0x0,0x0,0x21,0x49,0x44,0x41,0x54,0x18,0xd3,0x63,0x60,0xc0,0x1,0x1e,0x3c,0x80,0x32,0x98,0xd0,0x65,0xa8,0x21,0xc0,0xc8,0xf0,0x0,0x85,0xaf,0x80,0xa1,0x82,0x3e,0xee,0xc0,0x0,0x0,0x13,0x86,0x4,0x98,0x60,0x93,0x6c,0x5a,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xba,0x84,0x14,0xff,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xcb,0xd9,0xac,0x43,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x36,0x49,0x44,0x41,0x54,0x38,0x8d,0x63,0x60,0xa0,0x25,0x78,0xf0,0xe0,0xc1,0xff,0x7,0xf,0x1e,0xfc,0xc7,0xa7,0x86,0x89,0x52,0x4b,0x46,0xd,0x60,0x60,0x60,0x64,0x60,0x80,0x84,0x36,0x39,0x9a,0x15,0x14,0x14,0x18,0x29,0x76,0x1,0x5e,0x30,0x9a,0xe,0xe8,0x64,0x0,0xc5,0x0,0x0,0xc7,0x6e,0x12,0x94,0xf9,0x26,0x2e,0xdb,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char icon_close_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x4,0x0,0x0,0x0,0xb5,0xfa,0x37,0xea,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x6c,0x49,0x44,0x41,0x54,0x28,0xcf,0xad,0x90,0xd1,0xa,0x80,0x20,0xc,0x45,0xad,0xa7,0x6b,0xee,0x35,0xb1,0x3f,0xf3,0xbb,0x13,0xc,0xea,0x5f,0x5c,0xf,0x42,0x4d,0x1c,0x14,0xd4,0xde,0xc6,0x39,0xd3,0xdd,0x19,0xf3,0x53,0xd9,0x48,0x5e,0xf6,0xe4,0x6d,0x6c,0x30,0xa,0xd2,0xad,0x90,0x47,0x42,0x11,0xa,0xcd,0x76,0x5,0x63,0x9b,0x16,0xd9,0xb9,0x20,0x9f,0xbc,0x14,0x15,0xb,0x65,0x47,0x56,0x71,0x55,0x90,0xc1,0x60,0x1c,0x12,0x8f,0x5a,0x26,0x1e,0xd4,0x79,0xf9,0x45,0x5d,0x57,0x59,0xd2,0x85,0x36,0x51,0x87,0xfb,0xd0,0xef,0xe,0xf5,0x78,0xea,0x4f,0x75,0x2,0x30,0x98,0x34,0x72,0xa,0x11,0xfb,0xc2,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xba,0x84,0x14,0xff,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xcb,0xd9,0xac,0x43,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9b,0x49,0x44,0x41,0x54,0x38,0x8d,0xcd,0x92,0x31,0xe,0xc2,0x30,0x10,0x4,0x17,0xaa,0x3d,0x67,0xdb,0x58,0xd0,0xd3,0xf0,0xa3,0x7c,0x36,0x3c,0x82,0x48,0x44,0x22,0x6f,0xb1,0x4d,0x85,0x14,0x81,0xf,0x2c,0x28,0xe0,0xda,0xd5,0x8c,0x4e,0x77,0xb,0xfc,0xd5,0x98,0xd9,0x20,0x29,0x7a,0xb9,0xa4,0x68,0x66,0x83,0xb,0x93,0xcc,0x24,0xa7,0x9a,0x44,0x52,0x24,0x39,0x91,0xcc,0x55,0x89,0xa4,0xde,0xcc,0xce,0x24,0xb,0xc9,0x39,0x84,0xb0,0xf7,0xb2,0xae,0xeb,0x76,0xde,0x8a,0x4f,0x92,0x66,0xd8,0x91,0x5c,0x49,0x5e,0x9a,0xe1,0xb5,0x64,0x5,0x16,0x92,0x8b,0x7,0x6f,0x9b,0x8c,0x0,0x4a,0x29,0x9b,0x26,0x81,0xa4,0x3e,0xa5,0x34,0x2,0x38,0x2,0x58,0x0,0xcc,0x0,0xe,0x39,0xe7,0xd3,0xfa,0xb0,0xee,0xea,0x8f,0x7,0x7b,0xf5,0x9d,0xb7,0xb0,0x97,0x55,0x25,0x5f,0x17,0xe9,0x2e,0xf9,0xb8,0xca,0x3f,0x9b,0x1b,0x1a,0xe3,0x40,0x47,0xa0,0xda,0xda,0x61,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char icon_color_pick_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x4,0x0,0x0,0x0,0xb5,0xfa,0x37,0xea,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0xe0,0x49,0x44,0x41,0x54,0x28,0xcf,0x95,0x91,0xbf,0x6a,0xc2,0x60,0x14,0xc5,0xcf,0x17,0x82,0xcf,0xd0,0xad,0x75,0x13,0x12,0xa1,0x5b,0xc0,0xdd,0x35,0xe0,0x50,0xfc,0x43,0xfb,0x8,0x6e,0x8e,0x3e,0x44,0x1f,0xa0,0xf,0xd0,0xa9,0x88,0x53,0x85,0x3a,0x38,0x74,0x12,0xc1,0x45,0x1c,0x8c,0xf9,0xce,0x27,0x89,0xa0,0x19,0x3a,0x17,0xe2,0x17,0x87,0xb4,0x60,0x9a,0x48,0xc9,0x99,0xee,0xe5,0x7,0xe7,0x5e,0xce,0x1,0xca,0x4a,0x59,0xab,0xa,0xc0,0x16,0xf7,0x3c,0xb0,0x5,0x88,0x2c,0x96,0x8e,0x78,0x17,0xb3,0xd3,0x9b,0x78,0x11,0x26,0x80,0xe3,0xdd,0x8d,0xf9,0xc7,0xe0,0x1b,0x71,0xe2,0x1a,0xee,0xcf,0x16,0x3,0x46,0x96,0x57,0x97,0x78,0xfe,0x9d,0x93,0x18,0xfd,0xdc,0x7,0xb2,0xc3,0x90,0x3d,0x46,0xd4,0xd4,0xfe,0x53,0x21,0xf6,0x6c,0x40,0x76,0xa9,0xa9,0xd5,0x68,0x55,0x29,0xc4,0xca,0x62,0xe0,0xf,0x19,0xf1,0x4b,0x59,0x57,0xb0,0xec,0x0,0xf2,0x5e,0x3a,0x17,0xd8,0x7f,0x60,0xb0,0xad,0x3,0xb2,0xa6,0x76,0xfe,0x63,0xee,0xf6,0x3f,0x98,0x8d,0xd4,0xdc,0xb3,0x53,0xf3,0xac,0xc,0x40,0x34,0xb1,0x4e,0x36,0x9e,0x6d,0x4e,0x92,0x41,0xf5,0xb5,0x28,0xfd,0x31,0x35,0x3f,0x18,0xca,0x76,0x51,0x37,0x2,0xe0,0x5c,0xec,0xb1,0xc0,0xf4,0xf6,0xb3,0x74,0xb3,0x0,0x70,0x6,0x95,0x2,0x6f,0xae,0x29,0xa4,0x96,0x25,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x34,0x39,0x2b,0x30,0x32,0x3a,0x30,0x30,0xe3,0xb6,0x51,0xb2,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x34,0x39,0x2b,0x30,0x32,0x3a,0x30,0x30,0x92,0xeb,0xe9,0xe,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x1,0x55,0x49,0x44,0x41,0x54,0x38,0x8d,0xb5,0x92,0xb1,0x4a,0x3,0x41,0x14,0x45,0xef,0xdb,0x6c,0xac,0xf2,0x1,0xda,0xcd,0x40,0x4,0x25,0x11,0x4,0x8b,0x80,0x8d,0x20,0x88,0x5d,0x20,0x88,0x90,0x22,0x9d,0x9d,0xa0,0x85,0x58,0xeb,0x7,0x88,0xe0,0x7,0x58,0x8b,0x36,0x5a,0x88,0xa0,0xa5,0x85,0xa5,0x60,0x61,0xb0,0x70,0xb2,0xef,0x8d,0x44,0x41,0x21,0x1f,0x20,0x6c,0xf2,0x2c,0xcc,0xc2,0x12,0x92,0x8d,0x45,0xbc,0xe5,0xdc,0xb9,0x67,0xee,0xbc,0x19,0xe0,0xbf,0xe5,0xbd,0x2f,0x35,0x9b,0xcd,0x29,0x0,0x10,0x91,0x9a,0x88,0x7c,0x88,0xc8,0xa7,0x88,0xd4,0x0,0x80,0xb2,0xc2,0xcc,0x5c,0x21,0xa2,0x5b,0x22,0xba,0xef,0x76,0xbb,0x97,0x44,0x74,0x4a,0x44,0x61,0xdf,0xfe,0x32,0xc6,0x4c,0x87,0x59,0x0,0x0,0xdf,0x0,0x62,0x55,0xad,0x6,0x41,0x50,0x1d,0xf0,0x62,0x0,0x8,0xb2,0xd2,0xd6,0xda,0x27,0x0,0x27,0x83,0xeb,0xaa,0x1a,0x3,0xd8,0x19,0xb,0x60,0xe6,0x3a,0x80,0x6d,0x0,0xd,0x0,0x9d,0x14,0x60,0xcb,0x18,0x73,0x95,0x9,0x60,0xe6,0x3a,0x11,0x1d,0xc7,0x71,0xbc,0x6e,0x8c,0x39,0x53,0xd5,0xdd,0xc4,0xcb,0xe5,0x72,0x1b,0xc9,0x60,0x87,0x2,0xd2,0xe1,0x62,0xb1,0xf8,0xec,0xbd,0x2f,0x11,0xd1,0x51,0xaf,0xd7,0x3b,0x0,0xd0,0x51,0xd5,0x95,0x42,0xa1,0x30,0x3b,0xf2,0x64,0x11,0x79,0x77,0xce,0x95,0x81,0xdf,0x67,0x14,0x91,0x76,0xff,0x3a,0x60,0xe6,0x45,0x66,0xae,0xc,0xd,0x47,0x51,0xb4,0x29,0x22,0xed,0x56,0xab,0xb5,0xd0,0xdf,0x3c,0xe7,0xbd,0x7f,0x8b,0xa2,0xa8,0x31,0x7a,0x52,0x93,0x8,0x8b,0xc8,0x72,0xba,0xb6,0x73,0xae,0x9c,0xae,0x9d,0xa5,0x0,0x0,0x88,0x68,0xd,0xc0,0x8b,0xaa,0xbe,0x3a,0xe7,0xca,0x61,0x18,0xde,0xa9,0xea,0xbe,0xb5,0xf6,0x7c,0x1c,0x20,0xf9,0x89,0x4b,0x0,0x56,0xf3,0xf9,0xfc,0xd,0x80,0x79,0x55,0xdd,0xb3,0xd6,0x5e,0x8c,0xad,0x9e,0x0,0x54,0x75,0x86,0x88,0xae,0x1,0x3c,0x2,0x38,0x34,0xc6,0x3c,0xfc,0x25,0x3c,0x11,0xfd,0x0,0x28,0x54,0xbb,0xfe,0xad,0x99,0xe5,0xb8,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char icon_folder_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x4,0x0,0x0,0x0,0xb5,0xfa,0x37,0xea,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x40,0x49,0x44,0x41,0x54,0x28,0xcf,0x63,0x60,0xa0,0x14,0x30,0x32,0x30,0x3c,0x38,0xca,0x60,0x85,0x24,0x72,0x44,0xc1,0x16,0x5d,0xc1,0x7f,0x54,0x3d,0xa,0x8c,0xc8,0x3c,0x26,0x4c,0x43,0x1f,0xda,0x10,0x30,0x1,0xd5,0x3a,0x26,0x6,0x7c,0xc0,0x6,0xab,0x15,0xa8,0x60,0xc8,0x28,0x38,0x82,0x4b,0xf2,0xff,0x61,0x42,0xda,0x89,0x1,0x0,0x7c,0x5,0xb,0xf5,0x5d,0xb6,0xe9,0xbb,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x34,0x39,0x2b,0x30,0x32,0x3a,0x30,0x30,0xe3,0xb6,0x51,0xb2,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x34,0x39,0x2b,0x30,0x32,0x3a,0x30,0x30,0x92,0xeb,0xe9,0xe,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x5f,0x49,0x44,0x41,0x54,0x38,0x8d,0xed,0x8f,0xc1,0xd,0x80,0x30,0x8,0x45,0x9f,0x9d,0x84,0x39,0x4c,0x3b,0xbd,0x75,0x8f,0x32,0x9,0x5e,0xec,0xa5,0x9,0xa4,0xc6,0x26,0x5e,0x7c,0x17,0xe,0xc0,0xe3,0x3,0x5f,0xb3,0x1,0xb4,0xd6,0x4e,0x60,0x77,0x66,0xaa,0x88,0x14,0x4f,0x90,0xee,0xea,0x2d,0x3,0xe4,0x28,0x41,0x8a,0x9a,0x1d,0x55,0x75,0x25,0xfd,0x5,0x9b,0x11,0xd,0x54,0x11,0x29,0x53,0x9,0x1c,0x32,0x4c,0xbe,0x10,0xf1,0xb,0x16,0xa,0xea,0xd3,0x45,0x33,0x3b,0xde,0x1e,0x5f,0xc3,0x5,0x1f,0xc5,0x12,0x2c,0xc5,0x88,0xe1,0xb4,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char icon_play_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x4,0x0,0x0,0x0,0xb5,0xfa,0x37,0xea,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x6b,0x49,0x44,0x41,0x54,0x28,0xcf,0x63,0x60,0xa0,0x17,0x78,0x70,0xf8,0xc1,0xb5,0x7,0xde,0xf8,0x14,0xfc,0x7f,0xf0,0xff,0xc1,0xff,0x87,0x3b,0x1e,0x6a,0xa1,0xcb,0x30,0x21,0x73,0xfe,0xbb,0xff,0xbf,0xf8,0x60,0xca,0x13,0x61,0x64,0x31,0x46,0x98,0x9,0x48,0x62,0x1f,0x18,0x3b,0x7e,0x4d,0x50,0xfd,0x89,0x5b,0x1,0x3,0x3,0x3,0xc3,0x11,0x5,0x5b,0x2c,0x56,0x60,0x3,0xd8,0x14,0xbc,0x67,0xac,0xf8,0xed,0x2,0xe3,0xb0,0xa0,0x49,0xfe,0x61,0x98,0xc9,0x52,0x2f,0xf3,0x16,0x21,0x80,0xa2,0x80,0x71,0x27,0x43,0x91,0xfc,0x35,0xf2,0x2,0x8a,0x96,0x0,0x0,0xbc,0x2d,0x27,0xc4,0x79,0x12,0x82,0x82,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xba,0x84,0x14,0xff,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xcb,0xd9,0xac,0x43,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0xa2,0x49,0x44,0x41,0x54,0x38,0x8d,0x63,0x60,0x18,0xf2,0x80,0x11,0x99,0xf3,0xe0,0xc1,0x83,0xc3,0xc,0xc,0xc,0xc2,0xc,0xc,0xc,0xa5,0xa,0xa,0xa,0x5b,0xc9,0x31,0xe0,0x3f,0x5c,0x82,0x91,0x71,0x27,0x3,0x3,0x43,0x91,0xbc,0xbc,0xfc,0x35,0x7c,0x6,0x30,0xe1,0x92,0xf8,0xff,0xff,0xbf,0xfb,0xff,0xff,0xff,0x2f,0x3e,0x78,0xf0,0x60,0xca,0x93,0x27,0x4f,0x84,0x49,0x76,0x1,0x1a,0xf8,0xc0,0xc8,0xc8,0xd8,0xf1,0xeb,0xd7,0xaf,0x9,0xaa,0xaa,0xaa,0x3f,0x89,0x72,0x1,0x1a,0x10,0xf8,0xff,0xff,0x7f,0x7,0x2b,0x2b,0xeb,0x1e,0x74,0x9,0x62,0xd,0xc0,0x9,0x88,0x35,0xe0,0x3d,0x23,0x23,0x63,0xc5,0xef,0xdf,0xbf,0x5d,0xd0,0x25,0x58,0x8,0x68,0xfc,0xc3,0xc0,0xc0,0x30,0x93,0x85,0x85,0xa5,0x5e,0x46,0x46,0xe6,0x2d,0x36,0x5,0x38,0xd,0x20,0x36,0x1a,0xd1,0xd,0x38,0xc2,0x0,0x4d,0x48,0xf2,0xf2,0xf2,0x44,0x25,0xa4,0x61,0x0,0x0,0x1e,0x57,0x33,0x3c,0xcc,0xe7,0x34,0x69,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char icon_reload_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x4,0x0,0x0,0x0,0xb5,0xfa,0x37,0xea,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0xe8,0x49,0x44,0x41,0x54,0x28,0xcf,0xa5,0x91,0x31,0x4e,0x2,0x51,0x10,0x86,0x3f,0x16,0x22,0x5b,0x10,0x88,0x5a,0x1a,0x4a,0x1b,0xd7,0x4,0x4a,0x6e,0x60,0x65,0xa3,0xc1,0xc4,0x8e,0x8e,0x46,0x38,0x90,0x5,0xa5,0x17,0x90,0x46,0xf,0x80,0x56,0x84,0x2,0x48,0xc,0xc9,0xee,0x3c,0x56,0xe,0x60,0xd0,0x64,0x2d,0xde,0x40,0xe3,0xbe,0xdd,0x4d,0xec,0x98,0x6a,0x26,0xf3,0x4d,0xe6,0x9f,0x7f,0xe0,0xd0,0x28,0x65,0xe9,0xaa,0x5a,0xe9,0x97,0xee,0xb9,0x4,0xe6,0xfa,0x64,0x1f,0xcf,0x7f,0xb,0x40,0x7c,0x66,0xc7,0xb4,0x72,0xa3,0xb3,0xf2,0x75,0x73,0x3,0x5e,0x3a,0x6d,0xc7,0xb4,0x88,0xe9,0x26,0x8d,0xa4,0xb1,0xbb,0xe1,0x83,0xb6,0x7d,0x5e,0x55,0x1d,0x1e,0xd,0x45,0xc5,0xc4,0x27,0x69,0x6d,0x8e,0xc5,0x88,0x86,0xf,0xe,0x90,0x77,0x51,0xb9,0xcd,0x8b,0xb,0xbb,0xa2,0x32,0x71,0x2b,0xb8,0x80,0xe4,0x35,0xf,0xd8,0x17,0x20,0x0,0xf,0x64,0x24,0x4a,0xd,0xfc,0x2f,0x19,0x65,0x80,0xf7,0x27,0xdf,0x3,0x7f,0xc0,0x12,0x80,0xa5,0x3f,0xc8,0xdd,0x7f,0x5,0x2c,0x52,0x49,0x81,0x6c,0x65,0x6b,0x82,0xac,0xfd,0x79,0x6a,0xd6,0x5,0x91,0x51,0x2f,0xea,0x39,0xc3,0xea,0xe1,0x9d,0x59,0x8b,0xca,0x74,0x71,0x54,0x70,0xd2,0x5d,0xa4,0xff,0x18,0x55,0x88,0x6f,0xde,0x74,0xf8,0xd3,0x69,0x6e,0xe,0x7e,0x24,0x0,0x7b,0x27,0x64,0x59,0x3b,0x41,0xb6,0x9a,0xe,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xba,0x84,0x14,0xff,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xcb,0xd9,0xac,0x43,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x1,0x59,0x49,0x44,0x41,0x54,0x38,0x8d,0xcd,0x92,0x31,0x4b,0x3,0x31,0x18,0x86,0x9f,0x5c,0xe,0xec,0x20,0x76,0x70,0x39,0xd0,0xe3,0xba,0x74,0x51,0x41,0xdd,0xfc,0x7,0xba,0xb8,0x8,0x52,0xec,0x2e,0x4e,0x3a,0x88,0x3f,0xa3,0xa3,0x53,0x7,0x47,0x67,0x41,0x17,0xdd,0x9c,0x5c,0x3b,0xd8,0x82,0x64,0x68,0xca,0xd5,0x55,0x11,0x3c,0x1a,0x87,0x24,0x2e,0xd7,0x72,0x9e,0x9e,0xab,0xbe,0xd3,0xc7,0x1b,0x9e,0x37,0xf9,0xbe,0x7c,0xf0,0xd7,0x12,0x3f,0x99,0x4a,0xa9,0xb9,0x30,0xc,0x8f,0x84,0x10,0x7,0xc0,0x5a,0x6e,0x3f,0x3a,0xe7,0x2e,0xad,0xb5,0xdd,0x66,0xb3,0xf9,0x51,0x19,0x90,0xa6,0xe9,0x92,0xb5,0xf6,0x6,0x58,0xaf,0xb8,0xb4,0x27,0xa5,0xdc,0x8d,0xe3,0xf8,0x19,0x20,0x28,0xdf,0x5c,0x80,0x53,0x60,0xdf,0x18,0x53,0x37,0xc6,0xd4,0xbd,0xf7,0x7b,0xc0,0x13,0xb0,0x61,0xad,0xbd,0x56,0x4a,0xcd,0x1,0x84,0xc5,0x80,0x30,0xc,0x8f,0xa6,0xb0,0x94,0x72,0x33,0x8e,0xe3,0x97,0xc2,0xf1,0xd5,0x68,0x34,0xba,0xf7,0xde,0xf7,0x80,0xd,0x29,0xe5,0x21,0x70,0xfe,0xe5,0x5,0x42,0x88,0x76,0x5e,0x9e,0x96,0x60,0x0,0x92,0x24,0x79,0x75,0xce,0x9d,0x1,0x4,0x41,0xd0,0xfe,0xd6,0x2,0xb0,0x2,0x60,0x8c,0xb9,0xab,0xe8,0x1f,0x6b,0xed,0x6d,0x5e,0xae,0xce,0x2,0xb4,0xd6,0x17,0x5a,0x6b,0x7,0xcc,0x3,0xd4,0x6a,0xb5,0x37,0xad,0xf5,0xc5,0x4f,0x1,0x41,0x10,0x7c,0x19,0x7c,0x90,0x3,0xc7,0xc0,0xa0,0xe0,0xf,0x72,0xef,0x9b,0x84,0x10,0xdb,0x79,0xd9,0x9f,0x5,0x44,0x51,0x94,0x9,0x21,0x5a,0x40,0x6,0x64,0x42,0x88,0x56,0x14,0x45,0x59,0x19,0x1e,0x8f,0xc7,0x8b,0x52,0xca,0xe,0x80,0x73,0xee,0x12,0xa,0xbf,0x90,0x24,0x49,0x7f,0x38,0x1c,0x1e,0x3,0x34,0x1a,0x8d,0x7e,0x11,0x54,0x4a,0x2d,0x48,0x29,0x77,0xac,0xb5,0x1d,0xef,0xfd,0x32,0xd0,0x9b,0x4c,0x26,0x5d,0xa8,0xd8,0xc4,0xb2,0xf2,0xf9,0x4c,0x55,0xbd,0x48,0xbf,0xe8,0x1d,0x78,0x70,0xce,0x9d,0x64,0x59,0xb6,0x35,0x85,0xff,0x87,0x3e,0x1,0x53,0x7,0x87,0x11,0xd3,0x3a,0x9b,0x9e,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +}; + + +static const unsigned char icon_snap_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0xc2,0x49,0x44,0x41,0x54,0x38,0x8d,0xad,0x90,0xbd,0xa,0xc2,0x30,0x14,0x85,0xbf,0x5b,0x5c,0x23,0xe8,0x6c,0x9f,0xc1,0xb7,0xd0,0x47,0xd1,0x47,0x70,0x48,0xa1,0x43,0x57,0xe9,0xd3,0x88,0x93,0xef,0xe0,0xea,0x5c,0x9d,0x1d,0xb2,0x96,0xc6,0xa1,0x9,0xd4,0xd8,0xd8,0x4a,0xfd,0x20,0x10,0xee,0xcf,0xe1,0xdc,0x3,0x1d,0x8c,0x31,0xd6,0x18,0x63,0x9,0x88,0xd5,0x1,0x92,0xbe,0xe2,0x2f,0x4c,0x16,0x90,0x98,0xb5,0x21,0x94,0x52,0xf2,0x17,0x7,0x6f,0x7c,0xb,0x2b,0xc6,0x64,0x7,0xb3,0xa1,0x1,0x5b,0x14,0x29,0x50,0x2,0x1b,0x0,0x44,0x2e,0x34,0xcd,0x41,0xb2,0xec,0x6,0x20,0xdd,0x61,0x6f,0xdf,0x7,0xe4,0x96,0xaf,0xc0,0x32,0xd0,0x7d,0x2,0x6b,0xd1,0xba,0x4a,0xfc,0xdd,0x91,0xdb,0x4b,0xb7,0x7c,0x2,0x56,0xd4,0x75,0xa,0x9c,0x81,0x5,0x70,0x84,0xe1,0xc,0x5a,0xdb,0x75,0xbd,0x17,0xad,0x1f,0x92,0xe7,0x77,0x60,0xe7,0x7a,0x5b,0x80,0x44,0x29,0x25,0xfe,0xf5,0x8,0x28,0x0,0xb7,0xd8,0x46,0xa0,0x75,0xe5,0xbe,0xf3,0x31,0xe,0x7e,0x23,0xcc,0xc2,0x3a,0xc2,0xb9,0x58,0xfd,0x83,0xc9,0x2,0x63,0x78,0x1,0x4a,0x50,0x70,0x86,0xcc,0x86,0x2,0x4,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -200,17 +225,17 @@ static const unsigned char icon_stop_png[]={ static const unsigned char icon_zoom_less_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x0,0x0,0x0,0x0,0x3a,0x98,0xa0,0xbd,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x74,0x52,0x4e,0x53,0x0,0x0,0x76,0x93,0xcd,0x38,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x17,0x49,0x44,0x41,0x54,0x18,0xd3,0x63,0x60,0x18,0x10,0xc0,0xc8,0xf0,0x0,0x85,0xaf,0xc0,0x34,0x30,0xee,0xc0,0x0,0x0,0x97,0xf9,0x1,0x4,0xea,0x8f,0x4a,0x96,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x34,0x39,0x2b,0x30,0x32,0x3a,0x30,0x30,0xe3,0xb6,0x51,0xb2,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x34,0x39,0x2b,0x30,0x32,0x3a,0x30,0x30,0x92,0xeb,0xe9,0xe,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x25,0x49,0x44,0x41,0x54,0x38,0x8d,0x63,0x60,0x18,0x5,0xc3,0x0,0x30,0x32,0x30,0x30,0x30,0x3c,0x78,0xf0,0xe0,0x3f,0x39,0x9a,0x15,0x14,0x14,0x18,0x99,0xa8,0xeb,0x9e,0x51,0x30,0x44,0x1,0x0,0xff,0xa9,0x4,0x4,0x4a,0xae,0x20,0xfa,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char icon_zoom_more_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x0,0x0,0x0,0x0,0x3a,0x98,0xa0,0xbd,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x74,0x52,0x4e,0x53,0x0,0x0,0x76,0x93,0xcd,0x38,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x21,0x49,0x44,0x41,0x54,0x18,0xd3,0x63,0x60,0xc0,0x1,0x1e,0x3c,0x80,0x32,0x98,0xd0,0x65,0xa8,0x21,0xc0,0xc8,0xf0,0x0,0x85,0xaf,0x80,0xa1,0x82,0x3e,0xee,0xc0,0x0,0x0,0x13,0x86,0x4,0x98,0x60,0x93,0x6c,0x5a,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xba,0x84,0x14,0xff,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xcb,0xd9,0xac,0x43,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x36,0x49,0x44,0x41,0x54,0x38,0x8d,0x63,0x60,0xa0,0x25,0x78,0xf0,0xe0,0xc1,0xff,0x7,0xf,0x1e,0xfc,0xc7,0xa7,0x86,0x89,0x52,0x4b,0x46,0xd,0x60,0x60,0x60,0x64,0x60,0x80,0x84,0x36,0x39,0x9a,0x15,0x14,0x14,0x18,0x29,0x76,0x1,0x5e,0x30,0x9a,0xe,0xe8,0x64,0x0,0xc5,0x0,0x0,0xc7,0x6e,0x12,0x94,0xf9,0x26,0x2e,0xdb,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char icon_zoom_reset_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x4,0x0,0x0,0x0,0xb5,0xfa,0x37,0xea,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x4e,0x49,0x44,0x41,0x54,0x28,0xcf,0x63,0x60,0x20,0x6,0x3c,0xc,0x7b,0xf0,0xff,0xc1,0x7f,0xec,0x22,0x8c,0xc,0xc,0xcf,0x44,0x7e,0x5d,0x65,0x10,0x63,0x60,0x50,0x60,0x84,0x49,0x23,0x8b,0x30,0x31,0x30,0xfc,0x9a,0xc6,0x20,0x86,0x6a,0x22,0xa6,0x8,0x3,0xcc,0x40,0x84,0x55,0x30,0x16,0x13,0x21,0xf7,0xb1,0xa0,0x72,0x11,0xee,0x80,0x1,0x82,0x26,0x50,0x5d,0x1,0x7a,0x80,0xd,0xe,0x5f,0x10,0x4,0x0,0xfc,0xc5,0x22,0x8c,0x12,0xab,0xcb,0x61,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xba,0x84,0x14,0xff,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xcb,0xd9,0xac,0x43,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x6f,0x49,0x44,0x41,0x54,0x38,0x8d,0xdd,0x91,0xbb,0xd,0x80,0x30,0x10,0x43,0x1f,0x11,0x23,0x20,0xea,0x4c,0xc5,0x62,0x48,0xec,0xc0,0x56,0x97,0x26,0x43,0xa4,0x31,0x15,0x12,0x45,0x72,0x8a,0x14,0xa,0x84,0xab,0xfb,0x58,0x3e,0xeb,0xc,0x83,0x98,0xee,0x22,0xa5,0xb4,0x49,0x3a,0x1,0x62,0x8c,0x53,0x8d,0x5c,0xe3,0x4,0x80,0x9c,0xf3,0x22,0x69,0xf7,0x2e,0xb5,0x38,0x1,0xa0,0x94,0x72,0x0,0xab,0x27,0xd0,0xc3,0xc1,0xcc,0x64,0x66,0x6a,0xf5,0xb5,0x59,0x70,0x15,0x3b,0x30,0x7b,0xcb,0xd6,0x33,0x9f,0x18,0x76,0xf0,0x71,0x81,0x5a,0xa,0xaf,0x3b,0xf8,0x41,0xa,0xc3,0xb8,0x0,0x6c,0x9c,0x3f,0xb8,0x84,0xfc,0x5b,0x85,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -235,7 +260,7 @@ static const unsigned char logo_png[]={ static const unsigned char option_arrow_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0xc,0x8,0x4,0x0,0x0,0x0,0xfc,0x7c,0x94,0x6c,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x4,0x4e,0x1d,0x2,0xaf,0x0,0x0,0x0,0x5f,0x49,0x44,0x41,0x54,0x18,0xd3,0x63,0x60,0x20,0xc,0xee,0x27,0xdc,0x4f,0xc0,0x22,0xfc,0x50,0xfb,0xc1,0x97,0x7,0x5f,0x1e,0x6a,0xc3,0xf8,0x4c,0x10,0xea,0x5,0xf7,0xff,0x55,0xc,0xdc,0xc,0xdc,0xff,0x57,0xbd,0xe0,0x46,0x91,0xf8,0x39,0x85,0x41,0x8b,0x81,0x81,0x81,0x81,0x41,0xeb,0xe7,0x14,0x22,0x6c,0xc5,0x7,0x1e,0xce,0x7f,0xf0,0x1f,0x2,0x1f,0xce,0x87,0x88,0x30,0xc2,0x2c,0xff,0x71,0x8a,0x41,0x8b,0x81,0x81,0xe1,0x1a,0x87,0x99,0xc4,0x57,0xbc,0xce,0x25,0xec,0x41,0x74,0x0,0x0,0xec,0x66,0x28,0xba,0x76,0x22,0x7a,0x72,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xba,0x84,0x14,0xff,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xcb,0xd9,0xac,0x43,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0xc,0x8,0x6,0x0,0x0,0x0,0x56,0x75,0x5c,0xe7,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x98,0x49,0x44,0x41,0x54,0x28,0x91,0xbd,0x91,0xb1,0xd,0xc2,0x30,0x10,0x45,0xdf,0xd1,0xb8,0xf0,0x2,0xee,0xdc,0x87,0x1,0xd8,0x24,0xb5,0xe9,0x19,0x87,0x1e,0xea,0x6c,0xc2,0x0,0xa4,0xb5,0xdc,0x79,0x1,0x17,0xae,0x8e,0x26,0x48,0x76,0x14,0x40,0x48,0x88,0xdf,0xfd,0xf7,0xef,0x4b,0x77,0x3a,0xf8,0x85,0x62,0x8c,0x21,0xc6,0x18,0xb6,0x32,0x59,0x83,0x94,0xd2,0x5e,0x55,0x6f,0x0,0x22,0x72,0xf0,0xde,0xdf,0xdb,0x7c,0xd7,0x9a,0x9c,0xb3,0x55,0xd5,0x9,0xb0,0x80,0x55,0xd5,0x29,0xe7,0x6c,0x5f,0x16,0x6a,0xad,0x67,0x60,0x68,0xd0,0xb0,0xb0,0x3f,0xaa,0x3b,0x3a,0xa5,0x74,0x51,0xd5,0xd0,0xd,0x88,0x5c,0xbd,0xf7,0xc7,0xa7,0xef,0x6e,0x30,0xc6,0x9c,0x80,0xb9,0x41,0xf3,0xc2,0xd8,0x2c,0x38,0xe7,0x8a,0x88,0x8c,0x40,0x1,0x8a,0x88,0x8c,0xce,0xb9,0xf2,0x71,0xcf,0x77,0x8f,0xfb,0x5a,0xf,0x28,0x4a,0x37,0xff,0x58,0x46,0x7b,0x50,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -280,7 +305,7 @@ static const unsigned char popup_bg_disabled_png[]={ static const unsigned char popup_checked_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x4,0x0,0x0,0x0,0x6e,0x6,0x76,0x0,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x6c,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0x40,0x3,0x8c,0x8,0xe6,0xd,0x5e,0xf6,0xbd,0x8c,0x3f,0x99,0x60,0xdc,0xff,0x8c,0x1c,0xb,0x18,0x4d,0x19,0xb8,0xe0,0xf2,0xf,0x6a,0x1e,0xfc,0x7f,0xf0,0xee,0xb1,0xa,0xe3,0x83,0xc3,0xc,0x9c,0x7f,0xbc,0x58,0x4c,0x18,0x36,0x33,0x30,0x30,0xf8,0x2a,0x6c,0x63,0xf9,0xcf,0xce,0x68,0xcc,0x72,0x80,0x41,0x92,0x81,0x89,0xa1,0x46,0x61,0x1b,0x3,0x3,0xc3,0x1d,0xb1,0x7,0x97,0x1f,0xfc,0x7f,0xf0,0xff,0xc1,0xda,0xff,0x8c,0x50,0x5b,0xee,0x88,0xb1,0x6c,0x65,0xf8,0xfd,0xc3,0x5d,0xe3,0x33,0x3,0x3,0x3,0x3,0x0,0x6a,0x54,0x21,0x0,0x96,0x26,0x52,0xa9,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xba,0x84,0x14,0xff,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xcb,0xd9,0xac,0x43,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0xa3,0x49,0x44,0x41,0x54,0x18,0x95,0x85,0xcd,0xa1,0xa,0xc2,0x50,0x0,0x85,0xe1,0xff,0xdc,0x5d,0xd8,0x14,0x4,0xab,0x69,0x37,0xac,0x98,0xd5,0x27,0xb0,0x89,0x16,0x8b,0xd5,0xf7,0xd0,0xec,0x73,0xf8,0x4,0x16,0x61,0x4d,0x10,0xc,0x16,0xa3,0x61,0x71,0xab,0x16,0xeb,0x84,0x3b,0xae,0x45,0x8b,0xa,0x9e,0x78,0xce,0x7,0x7,0xfe,0x44,0xbf,0xca,0xa2,0x28,0x3a,0x71,0x1c,0x1f,0x24,0x3d,0xcc,0xe7,0x18,0x42,0x50,0x92,0x24,0x5b,0x49,0x23,0xa0,0xfd,0x5,0xaa,0xaa,0x5a,0x1,0x73,0xe0,0x1e,0x45,0xd1,0x42,0x65,0x59,0x9e,0x80,0x96,0xf7,0x7e,0x62,0xad,0x1d,0x2,0xfb,0x97,0x9d,0x39,0xe7,0x72,0x1b,0x42,0x88,0x25,0xd,0xac,0xb5,0x47,0xa0,0x7,0x18,0x60,0xed,0x9c,0xcb,0x1,0x4c,0xd3,0x34,0x53,0xe0,0xa,0xf4,0x81,0x2e,0xb0,0x4b,0xd3,0x74,0xf3,0xbe,0x34,0x59,0x96,0xdd,0xbc,0xf7,0x63,0xe0,0x2,0x9c,0xeb,0xba,0x5e,0x4a,0xa,0x6f,0xf0,0x4,0x57,0x3d,0x2c,0x27,0x2b,0xe9,0x62,0x6b,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -390,12 +415,12 @@ static const unsigned char selection_oof_png[]={ static const unsigned char spinbox_updown_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x4,0x0,0x0,0x0,0xb5,0xfa,0x37,0xea,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x76,0x49,0x44,0x41,0x54,0x28,0xcf,0x63,0x60,0x20,0xd,0xdc,0x4f,0x7f,0x98,0x86,0x47,0xfa,0x81,0xe5,0x83,0x1f,0xf,0x7e,0x3d,0xb2,0x45,0x16,0x63,0x44,0xd2,0x2d,0xc1,0x78,0x86,0x41,0x9a,0x81,0x81,0xe1,0x5,0xb3,0x89,0xec,0x53,0x98,0x28,0x13,0x8c,0x71,0x86,0x95,0x61,0x15,0x83,0x34,0x3,0x3,0x3,0x3,0x83,0xc4,0xdf,0x35,0xb7,0xd9,0x31,0x14,0x8,0x4f,0x61,0x44,0x18,0x6d,0xc1,0x36,0x93,0x44,0xc7,0xd3,0x7,0xdc,0x9f,0xf9,0xe0,0x3f,0x2,0x3e,0x9c,0x81,0xe1,0x8b,0xb7,0x39,0xff,0xf,0xc3,0x55,0x1f,0xff,0x95,0x4f,0x74,0x40,0xa1,0x5a,0x63,0x81,0x19,0xd4,0x68,0xe0,0x61,0x1a,0xde,0xc8,0xc2,0x6,0x0,0x74,0x4d,0x32,0x61,0xa3,0xda,0x8e,0xb3,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xba,0x84,0x14,0xff,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xcb,0xd9,0xac,0x43,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0xcd,0x49,0x44,0x41,0x54,0x38,0x8d,0xe5,0x53,0x31,0xe,0x82,0x40,0x10,0x9c,0x5d,0x22,0x3e,0x80,0x86,0xc4,0x0,0xe1,0xf,0x16,0x5a,0x58,0xf9,0x5,0xe3,0x13,0xd0,0xc2,0xc4,0xcf,0xd8,0xf0,0x5,0xe3,0x1f,0x2c,0x2c,0x6c,0xf8,0x1,0xc5,0x72,0x85,0x9,0xd,0xf,0x10,0x43,0xce,0x86,0x82,0xe0,0xe9,0x19,0x8d,0x95,0x53,0xce,0xce,0x6e,0x26,0x99,0x59,0xe0,0x97,0x10,0x91,0x95,0x52,0x2a,0x79,0xa5,0xa1,0x67,0x83,0xa2,0x28,0xa6,0x0,0x8e,0x0,0x98,0x99,0xe7,0x61,0x18,0x9e,0xde,0x3e,0x20,0x22,0x3e,0x11,0x65,0x0,0x46,0x2d,0x55,0x3a,0x8e,0x33,0xe,0x82,0xe0,0xd2,0xd7,0x72,0x9f,0xc8,0xb2,0x6c,0x0,0x60,0xdf,0x59,0x6,0x0,0xbf,0x69,0x9a,0x43,0x9e,0xe7,0x43,0xeb,0x1,0xcf,0xf3,0x76,0x44,0x34,0x33,0x18,0x9b,0xb8,0xae,0x9b,0x9a,0x1c,0xff,0x3b,0x1e,0x62,0x14,0x91,0x94,0x88,0x8c,0xe5,0x21,0xa2,0x34,0x8a,0xa2,0x75,0x97,0x7b,0x48,0xa1,0xaa,0xaa,0x8d,0xd6,0xda,0x54,0x9a,0x73,0x5d,0xd7,0x5b,0xab,0x83,0xd6,0xc5,0xe7,0x45,0x2,0x80,0x38,0x8e,0x4b,0xad,0xf5,0x2,0xc0,0x15,0xc0,0x8d,0x99,0x97,0xa6,0x65,0x2b,0x94,0x52,0x89,0xed,0x99,0xbe,0xc6,0x1d,0x31,0x1f,0x40,0xdc,0x74,0x8a,0x5b,0xc1,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char submenu_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x4,0x0,0x0,0x0,0x6e,0x6,0x76,0x0,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x4,0x4e,0x1d,0x2,0xaf,0x0,0x0,0x0,0x4d,0x49,0x44,0x41,0x54,0x8,0xd7,0x55,0xc8,0xa1,0x19,0x40,0x40,0x18,0x0,0xd0,0x77,0x8a,0x60,0x1,0x4d,0xb7,0x80,0x4d,0x64,0x3,0x18,0xc7,0x14,0xf6,0xa1,0xba,0x68,0x81,0xb,0xd2,0x2f,0xf9,0xbe,0xf3,0xe2,0x43,0x8e,0x1c,0x39,0xae,0x5,0x48,0xe4,0x0,0x25,0x4d,0xc3,0x41,0xe3,0xd3,0xc5,0x7e,0x77,0x75,0x30,0x3e,0xdb,0x3f,0xf0,0x8f,0xb3,0x5d,0xeb,0x28,0x69,0xee,0x4b,0x15,0xb1,0xe,0x7,0xbc,0x18,0xe0,0x15,0x49,0xfb,0x84,0x18,0x58,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xba,0x84,0x14,0xff,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xcb,0xd9,0xac,0x43,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x64,0x49,0x44,0x41,0x54,0x18,0x95,0x7d,0xca,0x21,0x12,0x80,0x20,0x14,0x45,0xd1,0xf7,0x2d,0x4,0x36,0x40,0x63,0xa8,0xba,0x1f,0xbb,0x9d,0xe5,0xb8,0x0,0xb3,0xfb,0xd1,0xc,0x8d,0xd,0x10,0x48,0xcf,0x22,0x6,0xc7,0xef,0x6d,0x77,0xe6,0x8,0x0,0xa4,0x94,0x88,0x3b,0x92,0x4b,0x8,0x61,0xeb,0x3f,0xe0,0x95,0x88,0xac,0x39,0xe7,0x49,0x5,0x0,0x2c,0xc9,0xbd,0x94,0x62,0x35,0x0,0x0,0x63,0x6b,0x6d,0xfd,0x3,0x4f,0x1a,0x38,0x8d,0x31,0x51,0x3,0x55,0x44,0x66,0xe7,0x5c,0xfd,0x4,0x24,0xa3,0xf7,0xfe,0xe8,0x7f,0x1,0xe,0xc2,0x1e,0x10,0xa,0xf0,0x33,0x4c,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -410,7 +435,7 @@ static const unsigned char tab_behind_png[]={ static const unsigned char tab_close_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x4,0x0,0x0,0x0,0xb5,0xfa,0x37,0xea,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0xb9,0x49,0x44,0x41,0x54,0x28,0xcf,0xad,0x90,0x5d,0xa,0x82,0x40,0x14,0x85,0xbf,0x31,0xb7,0xa0,0xd4,0x63,0x50,0x94,0x60,0x4b,0x28,0xe9,0x67,0x11,0x2e,0x36,0xa3,0xb6,0x90,0x82,0xc5,0x8,0xce,0x63,0xd0,0x12,0x34,0xa7,0x87,0xc9,0x1c,0x7b,0xa,0xea,0x3c,0xdd,0xcb,0xf9,0xe,0xf7,0x70,0xe1,0x4f,0x2a,0xe3,0xc2,0xb7,0xf7,0xc2,0x2f,0xe3,0x9e,0xad,0x1a,0x95,0x76,0x48,0xe1,0xab,0x54,0x35,0x6,0x71,0x0,0xea,0x44,0x67,0x84,0xee,0x49,0x8d,0x0,0xa4,0x37,0xd8,0x13,0x72,0xe5,0x8,0x20,0x4c,0x46,0x7a,0x6e,0x22,0x16,0x5c,0xd8,0x54,0xb5,0x99,0xf4,0x7a,0x7c,0xb3,0x80,0x16,0x11,0x52,0xd7,0x4,0x9d,0x6d,0x1,0x20,0x3d,0xf7,0x24,0x2,0xa0,0xd0,0xcb,0xd6,0x7e,0x75,0xf8,0x94,0xb0,0x62,0x4e,0xef,0x44,0xa0,0x25,0x39,0x13,0xe,0xa6,0xae,0x5,0xbc,0x4b,0xae,0xaa,0x48,0xa7,0xcc,0x6d,0x4,0x90,0x5e,0x79,0x56,0x5a,0xe5,0xe5,0xd0,0xde,0xc,0xe2,0x0,0xb8,0x5b,0x11,0x92,0xd5,0x91,0xa9,0x36,0xbd,0x3f,0x76,0x64,0xcc,0x74,0xf4,0xfd,0xab,0x7f,0xd2,0x13,0xed,0xc6,0x57,0xcd,0xb6,0x96,0x72,0x87,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xba,0x84,0x14,0xff,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xcb,0xd9,0xac,0x43,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0xfa,0x49,0x44,0x41,0x54,0x38,0x8d,0xcd,0x92,0x5f,0x4a,0xc4,0x30,0x10,0x87,0xbf,0xb1,0xb9,0xc2,0x16,0x7c,0x6b,0xc1,0xa2,0x85,0x7a,0x4,0x2d,0xfe,0x39,0xc4,0x9e,0x70,0x4f,0x61,0xc5,0x3d,0x83,0x5,0x95,0x4,0xd2,0x37,0x5,0x8f,0x90,0x94,0xf1,0xc5,0x4a,0x76,0xcd,0x22,0xf8,0xa2,0xf3,0x38,0xc3,0xef,0x9b,0xe4,0x4b,0xe0,0x5f,0x95,0xf7,0x7e,0xed,0x9c,0x2b,0xf,0xcd,0x9d,0x73,0xa5,0xf7,0x7e,0x9d,0xf6,0x8e,0xd2,0xb0,0x88,0x6c,0x8c,0x31,0x43,0xe,0xe2,0x9c,0x2b,0x8d,0x31,0x83,0x88,0x6c,0x52,0xc8,0x17,0x20,0xc6,0x38,0xa8,0xea,0x8,0x74,0xc6,0x98,0xed,0x34,0x4d,0xc7,0xcb,0xcc,0x5a,0xbb,0x2a,0x8a,0xe2,0xe,0xe8,0x80,0x17,0xe0,0x61,0x99,0x49,0xba,0xc5,0x5a,0xbb,0xfa,0xdc,0x72,0xe,0x3c,0x3,0xd7,0x21,0x84,0x98,0xf6,0x54,0xf5,0xaa,0xae,0xeb,0xb7,0x2c,0x60,0x1f,0x22,0x22,0x56,0x55,0x23,0xd0,0xe6,0xc2,0x59,0x40,0x2,0xd9,0x8a,0x48,0xbb,0x28,0x50,0xd5,0x8b,0xfd,0xf0,0x8e,0x83,0x9f,0x4a,0x44,0xb2,0xcb,0xbe,0x1,0x92,0x2b,0xb4,0xaa,0x6a,0x81,0x27,0xe0,0x4,0xb8,0x4f,0xc5,0x66,0x1,0x19,0x89,0x97,0x21,0x84,0x5e,0x55,0x1f,0x81,0xb3,0x1c,0x44,0xe,0x85,0x53,0x61,0xb9,0xd7,0xa9,0xaa,0xea,0x75,0xe7,0x4,0xc6,0x98,0x1b,0x11,0xe9,0x80,0x31,0xc6,0xd8,0xa7,0xc2,0x9a,0xa6,0x79,0x9f,0xe7,0xf9,0x16,0x18,0x81,0x53,0x55,0xed,0xb3,0xa2,0x7e,0xf3,0x95,0xff,0xbe,0x3e,0x0,0xbd,0x2c,0x93,0xec,0xb,0xe5,0x4f,0xb1,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -425,12 +450,12 @@ static const unsigned char tab_current_png[]={ static const unsigned char tab_menu_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x4,0x0,0x0,0x0,0xb5,0xfa,0x37,0xea,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x4c,0x49,0x44,0x41,0x54,0x28,0xcf,0x63,0x60,0x18,0x5,0xc,0xc,0xc,0xc,0x8c,0x30,0xc6,0x83,0xff,0xa8,0x12,0xa,0x50,0x19,0x26,0x42,0x26,0x10,0xaf,0x80,0x31,0x9e,0xe1,0x2b,0x5c,0xf4,0x3b,0x63,0x3a,0x16,0xb5,0xf7,0x35,0xee,0x5f,0x7a,0xf0,0xff,0xc1,0xff,0x7,0xd7,0x1f,0xeb,0x62,0x71,0x24,0x3,0x3,0x3,0xc3,0xb,0xee,0x9f,0x53,0x18,0x18,0xd8,0x73,0x24,0xbe,0x32,0x50,0x11,0x0,0x0,0x6,0x9b,0x11,0xfa,0xe0,0x26,0x3d,0x9f,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xba,0x84,0x14,0xff,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xcb,0xd9,0xac,0x43,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x6f,0x49,0x44,0x41,0x54,0x38,0x8d,0x63,0x60,0x18,0x5,0xa3,0x80,0x81,0x81,0x11,0x5d,0xe0,0xc1,0x83,0x7,0xff,0xf1,0x69,0x50,0x50,0x50,0x40,0xd1,0xc3,0x44,0xa9,0xb,0xa8,0x6f,0x0,0x23,0x23,0x63,0x3c,0x3,0x3,0xc3,0x57,0x2c,0x6a,0xbf,0x33,0x32,0x32,0xa6,0x63,0xa8,0xc7,0x66,0xea,0xfd,0xfb,0xf7,0x35,0x18,0x18,0x18,0x56,0x31,0x32,0x32,0xea,0x42,0x85,0x6e,0x30,0x33,0x33,0x87,0xc9,0xca,0xca,0x5e,0x26,0xca,0x0,0x6,0x6,0x6,0x86,0x17,0x2f,0x5e,0x70,0xff,0xfc,0xf9,0x73,0xa,0x3,0x3,0x3,0x3,0x3b,0x3b,0x7b,0x8e,0x84,0x84,0x4,0x36,0x57,0xd,0x2,0x0,0x0,0x67,0xf2,0x14,0xc2,0xc2,0xbe,0xf5,0xb5,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char tab_menu_hl_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x4,0x0,0x0,0x0,0xb5,0xfa,0x37,0xea,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x4c,0x49,0x44,0x41,0x54,0x28,0xcf,0x63,0x60,0x18,0x5,0xc,0xc,0xc,0xc,0x8c,0x30,0xc6,0x83,0xff,0xa8,0x12,0xa,0x50,0x19,0x26,0x42,0x26,0x10,0xaf,0x80,0x31,0x9e,0xe1,0x2b,0x5c,0xf4,0x3b,0x63,0x3a,0x16,0xb5,0xf7,0x35,0xee,0x5f,0x7a,0xf0,0xff,0xc1,0xff,0x7,0xd7,0x1f,0xeb,0x62,0x71,0x24,0x3,0x3,0x3,0xc3,0xb,0xee,0x9f,0x53,0x18,0x18,0xd8,0x73,0x24,0xbe,0x32,0x50,0x11,0x0,0x0,0x6,0x9b,0x11,0xfa,0xe0,0x26,0x3d,0x9f,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xba,0x84,0x14,0xff,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xcb,0xd9,0xac,0x43,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x6f,0x49,0x44,0x41,0x54,0x38,0x8d,0x63,0x60,0x18,0x5,0xa3,0x80,0x81,0x81,0x11,0x5d,0xe0,0xc1,0x83,0x7,0xff,0xf1,0x69,0x50,0x50,0x50,0x40,0xd1,0xc3,0x44,0xa9,0xb,0xa8,0x6f,0x0,0x23,0x23,0x63,0x3c,0x3,0x3,0xc3,0x57,0x2c,0x6a,0xbf,0x33,0x32,0x32,0xa6,0x63,0xa8,0xc7,0x66,0xea,0xfd,0xfb,0xf7,0x35,0x18,0x18,0x18,0x56,0x31,0x32,0x32,0xea,0x42,0x85,0x6e,0x30,0x33,0x33,0x87,0xc9,0xca,0xca,0x5e,0x26,0xca,0x0,0x6,0x6,0x6,0x86,0x17,0x2f,0x5e,0x70,0xff,0xfc,0xf9,0x73,0xa,0x3,0x3,0x3,0x3,0x3b,0x3b,0x7b,0x8e,0x84,0x84,0x4,0x36,0x57,0xd,0x2,0x0,0x0,0x67,0xf2,0x14,0xc2,0xc2,0xbe,0xf5,0xb5,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -490,7 +515,7 @@ static const unsigned char unchecked_png[]={ static const unsigned char updown_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x10,0x8,0x4,0x0,0x0,0x0,0x81,0x83,0xf6,0xf6,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x4,0x4e,0x1d,0x2,0xaf,0x0,0x0,0x0,0x86,0x49,0x44,0x41,0x54,0x18,0xd3,0x85,0x8e,0x21,0x12,0xc2,0x30,0x10,0x45,0x5f,0x98,0x9d,0xe9,0x70,0x81,0x3d,0x41,0x1c,0x75,0xe5,0x4,0xc4,0xc1,0x79,0xa9,0xb,0x6,0x49,0x5d,0x8b,0x5b,0x11,0x9d,0xb,0xd4,0xec,0x4c,0x10,0xad,0x43,0xf4,0xb9,0x6f,0xfe,0x7b,0x70,0x44,0x0,0x30,0x95,0x27,0xf8,0x23,0x56,0xb6,0x59,0xe6,0xd2,0x4a,0x2b,0xb3,0x29,0x4,0x53,0x79,0x71,0x61,0x1,0x7a,0xbe,0x7e,0xb,0xe5,0xc3,0x95,0xc5,0x13,0x48,0xa6,0x67,0x3a,0xb5,0x95,0xc9,0x53,0xac,0xb1,0x7a,0x62,0x6a,0xeb,0xa1,0x95,0x50,0xde,0x9c,0xfd,0x1e,0x2b,0x98,0xca,0xc8,0x7a,0x6a,0x1d,0x83,0x64,0x53,0x53,0xc9,0xc,0xad,0xb,0xa6,0x92,0xe9,0x77,0xed,0xe2,0xe9,0x3f,0x6c,0x4f,0x1f,0x61,0x7b,0x3a,0xe6,0x7,0x73,0x18,0x40,0x43,0x76,0xe2,0x28,0x4e,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xba,0x84,0x14,0xff,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x35,0x3a,0x35,0x30,0x2b,0x30,0x32,0x3a,0x30,0x30,0xcb,0xd9,0xac,0x43,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x2b,0x8a,0x3e,0x7d,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0xa6,0x49,0x44,0x41,0x54,0x28,0x91,0xa5,0x90,0x21,0xe,0xc2,0x50,0x10,0x44,0xdf,0x27,0x9b,0x10,0x2e,0xc0,0x9,0xd6,0x81,0xe3,0x6,0xe0,0xa0,0xd7,0x2d,0xae,0x18,0x24,0x95,0xc5,0x7d,0x51,0xdd,0xb,0x60,0xf6,0x67,0x31,0xfb,0x49,0xc1,0x20,0x3a,0x6a,0x93,0x99,0x9d,0xcc,0xc,0x2c,0x45,0xaa,0x47,0xce,0x79,0x2b,0x22,0x2d,0x80,0x99,0x5d,0x54,0x75,0xfa,0x8,0x82,0xec,0x80,0x7d,0xe8,0x7,0x33,0x3b,0xa9,0xea,0x94,0x82,0xbc,0x1,0x3b,0x60,0x8,0xc1,0x1e,0x78,0x9a,0xd9,0x51,0xc2,0x76,0x57,0xbf,0x0,0xaa,0x9b,0x88,0xb4,0x2b,0x77,0x7f,0x1,0x7d,0xb5,0x54,0xd5,0x29,0x84,0x7d,0x70,0x4b,0x6b,0x8e,0xe3,0x78,0x7,0x36,0x66,0x76,0xae,0xd5,0x22,0xf8,0x15,0x78,0x89,0xbb,0xaf,0x53,0x4a,0x7,0x11,0xe9,0x72,0xce,0x5f,0x21,0xdd,0xfd,0x21,0xa5,0x94,0x66,0x96,0xba,0x9b,0xd5,0x1c,0x4a,0x29,0xcd,0xff,0xa1,0x7e,0xa6,0xbe,0xc6,0xd4,0x9f,0x3c,0xcb,0xf1,0x6,0x8e,0x4e,0x65,0x44,0x6f,0x74,0x5c,0xa1,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -529,6 +554,11 @@ static const unsigned char vsplitter_png[]={ }; +static const unsigned char window_resizer_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x8,0x19,0x11,0x33,0x13,0xaa,0xc0,0xf,0x5f,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x2f,0x49,0x44,0x41,0x54,0x38,0xcb,0x63,0x60,0x18,0x5,0x24,0x81,0x17,0x2f,0x5e,0xf4,0xa3,0x8b,0x31,0x91,0xa2,0xb9,0xb9,0xb9,0x99,0x7c,0x9b,0xb3,0xb3,0xb3,0xfb,0x87,0x81,0x66,0x6c,0x81,0x48,0x92,0x66,0xa2,0x5c,0x43,0x91,0xe6,0x11,0xa,0x0,0x73,0x5b,0x34,0x19,0x10,0xa0,0xb6,0x7d,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +}; + + diff --git a/scene/resources/default_theme/window_resizer.png b/scene/resources/default_theme/window_resizer.png Binary files differnew file mode 100644 index 0000000000..ed51968c4e --- /dev/null +++ b/scene/resources/default_theme/window_resizer.png diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp index 67587a8f8b..679c8a000c 100644 --- a/scene/resources/dynamic_font.cpp +++ b/scene/resources/dynamic_font.cpp @@ -30,13 +30,22 @@ #include "dynamic_font.h" #include "os/file_access.h" +bool DynamicFontData::CacheID::operator< (CacheID right) const{ + + if (size<right.size) + return true; + if (mipmaps != right.mipmaps) + return right.mipmaps; + if (filter != right.filter) + return right.filter; + return false; +} - -Ref<DynamicFontAtSize> DynamicFontData::_get_dynamic_font_at_size(int p_size) { +Ref<DynamicFontAtSize> DynamicFontData::_get_dynamic_font_at_size(CacheID p_id){ - if (size_cache.has(p_size)) { - return Ref<DynamicFontAtSize>( size_cache[p_size] ); + if (size_cache.has(p_id)) { + return Ref<DynamicFontAtSize>( size_cache[p_id] ); } @@ -46,9 +55,8 @@ Ref<DynamicFontAtSize> DynamicFontData::_get_dynamic_font_at_size(int p_size) { dfas->font=Ref<DynamicFontData>( this ); - size_cache[p_size]=dfas.ptr(); - - dfas->size=p_size; + size_cache[p_id]=dfas.ptr(); + dfas->id=p_id; dfas->_load(); return dfas; @@ -169,11 +177,16 @@ Error DynamicFontAtSize::_load() { ERR_FAIL_COND_V( error, ERR_INVALID_PARAMETER ); }*/ - error = FT_Set_Pixel_Sizes(face,0,size); + error = FT_Set_Pixel_Sizes(face,0,id.size); ascent=face->size->metrics.ascender>>6; descent=-face->size->metrics.descender>>6; linegap=0; + texture_flags=0; + if (id.mipmaps) + texture_flags|=Texture::FLAG_MIPMAPS; + if (id.filter) + texture_flags|=Texture::FLAG_FILTER; //print_line("ASCENT: "+itos(ascent)+" descent "+itos(descent)+" hinted: "+itos(face->face_flags&FT_FACE_FLAG_HINTER)); @@ -270,6 +283,15 @@ Size2 DynamicFontAtSize::get_char_size(CharType p_char,CharType p_next,const Vec return ret; } +void DynamicFontAtSize::set_texture_flags(uint32_t p_flags){ + + texture_flags=p_flags; + for(int i=0;i<textures.size();i++) { + Ref<ImageTexture> &tex = textures[i].texture; + if (!tex.is_null()) + tex->set_flags(p_flags); + } +} float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2& p_pos, CharType p_char,CharType p_next,const Color& p_modulate,const Vector<Ref<DynamicFontAtSize> >& p_fallbacks) const { @@ -496,7 +518,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) { tex_x = 0; tex_y = 0; - int texsize = MAX(size*8,256); + int texsize = MAX(id.size*8,256); if (mw>texsize) texsize=mw; //special case, adapt to it? if (mh>texsize) @@ -555,7 +577,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) { if (tex.texture.is_null()) { tex.texture.instance(); - tex.texture->create_from_image(img,Texture::FLAG_VIDEO_SURFACE); + tex.texture->create_from_image(img,Texture::FLAG_VIDEO_SURFACE|texture_flags); } else { tex.texture->set_data(img); //update } @@ -595,25 +617,39 @@ DynamicFontAtSize::DynamicFontAtSize() { ascent=1; descent=1; linegap=1; + texture_flags=0; } DynamicFontAtSize::~DynamicFontAtSize(){ if (valid) { FT_Done_FreeType( library ); - font->size_cache.erase(size); + font->size_cache.erase(id); } } ///////////////////////// +void DynamicFont::_reload_cache(){ + + ERR_FAIL_COND(cache_id.size<1); + if (!data.is_valid()) + return; + data_at_size=data->_get_dynamic_font_at_size(cache_id); + for (int i=0;i<fallbacks.size();i++){ + fallback_data_at_size[i]=fallbacks[i]->_get_dynamic_font_at_size(cache_id); + } + + emit_changed(); + _change_notify(); +} void DynamicFont::set_font_data(const Ref<DynamicFontData>& p_data) { data=p_data; if (data.is_valid()) - data_at_size=data->_get_dynamic_font_at_size(size); + data_at_size=data->_get_dynamic_font_at_size(cache_id); else data_at_size=Ref<DynamicFontAtSize>(); @@ -628,23 +664,72 @@ Ref<DynamicFontData> DynamicFont::get_font_data() const{ void DynamicFont::set_size(int p_size){ - if (size==p_size) + if (cache_id.size==p_size) return; - size=p_size; - ERR_FAIL_COND(p_size<1); - if (!data.is_valid()) + cache_id.size=p_size; + _reload_cache(); +} + +int DynamicFont::get_size() const{ + + return cache_id.size; +} + +bool DynamicFont::get_use_mipmaps() const{ + + return cache_id.mipmaps; +} + +void DynamicFont::set_use_mipmaps(bool p_enable){ + + if (cache_id.mipmaps==p_enable) return; - data_at_size=data->_get_dynamic_font_at_size(size); - for(int i=0;i<fallbacks.size();i++) { - fallback_data_at_size[i]=fallbacks[i]->_get_dynamic_font_at_size(size); + cache_id.mipmaps=p_enable; + _reload_cache(); +} + +bool DynamicFont::get_use_filter() const{ + + return cache_id.filter; +} + +void DynamicFont::set_use_filter(bool p_enable){ + + if (cache_id.filter==p_enable) + return; + cache_id.filter=p_enable; + _reload_cache(); +} + +int DynamicFont::get_spacing(int p_type) const{ + + if (p_type == SPACING_TOP){ + return spacing_top; + }else if (p_type == SPACING_BOTTOM){ + return spacing_bottom; + }else if (p_type == SPACING_CHAR){ + return spacing_char; + }else if (p_type == SPACING_SPACE){ + return spacing_space; } - emit_changed(); - _change_notify(); + return 0; } -int DynamicFont::get_size() const{ - return size; +void DynamicFont::set_spacing(int p_type, int p_value){ + + if (p_type == SPACING_TOP){ + spacing_top=p_value; + }else if (p_type == SPACING_BOTTOM){ + spacing_bottom=p_value; + }else if (p_type == SPACING_CHAR){ + spacing_char=p_value; + }else if (p_type == SPACING_SPACE){ + spacing_space=p_value; + } + + emit_changed(); + _change_notify(); } float DynamicFont::get_height() const{ @@ -652,7 +737,7 @@ float DynamicFont::get_height() const{ if (!data_at_size.is_valid()) return 1; - return data_at_size->get_height(); + return data_at_size->get_height()+spacing_top+spacing_bottom; } float DynamicFont::get_ascent() const{ @@ -660,7 +745,7 @@ float DynamicFont::get_ascent() const{ if (!data_at_size.is_valid()) return 1; - return data_at_size->get_ascent(); + return data_at_size->get_ascent()+spacing_top; } float DynamicFont::get_descent() const{ @@ -668,7 +753,7 @@ float DynamicFont::get_descent() const{ if (!data_at_size.is_valid()) return 1; - return data_at_size->get_descent(); + return data_at_size->get_descent()+spacing_bottom; } @@ -677,7 +762,13 @@ Size2 DynamicFont::get_char_size(CharType p_char,CharType p_next) const{ if (!data_at_size.is_valid()) return Size2(1,1); - return data_at_size->get_char_size(p_char,p_next,fallback_data_at_size); + Size2 ret=data_at_size->get_char_size(p_char,p_next,fallback_data_at_size); + if (p_char==' ') + ret.width+=spacing_space+spacing_char; + else if (p_next) + ret.width+=spacing_char; + + return ret; } @@ -691,7 +782,7 @@ float DynamicFont::draw_char(RID p_canvas_item, const Point2& p_pos, CharType p_ if (!data_at_size.is_valid()) return 0; - return data_at_size->draw_char(p_canvas_item,p_pos,p_char,p_next,p_modulate,fallback_data_at_size); + return data_at_size->draw_char(p_canvas_item,p_pos,p_char,p_next,p_modulate,fallback_data_at_size)+spacing_char; } void DynamicFont::set_fallback(int p_idx,const Ref<DynamicFontData>& p_data) { @@ -699,7 +790,7 @@ void DynamicFont::set_fallback(int p_idx,const Ref<DynamicFontData>& p_data) { ERR_FAIL_COND(p_data.is_null()); ERR_FAIL_INDEX(p_idx,fallbacks.size()); fallbacks[p_idx]=p_data; - fallback_data_at_size[p_idx]=fallbacks[p_idx]->_get_dynamic_font_at_size(size); + fallback_data_at_size[p_idx]=fallbacks[p_idx]->_get_dynamic_font_at_size(cache_id); } @@ -707,7 +798,7 @@ void DynamicFont::add_fallback(const Ref<DynamicFontData>& p_data) { ERR_FAIL_COND(p_data.is_null()); fallbacks.push_back(p_data); - fallback_data_at_size.push_back(fallbacks[fallbacks.size()-1]->_get_dynamic_font_at_size(size)); //const.. + fallback_data_at_size.push_back(fallbacks[fallbacks.size()-1]->_get_dynamic_font_at_size(cache_id)); //const.. _change_notify(); emit_changed(); @@ -794,6 +885,13 @@ void DynamicFont::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_size","data"),&DynamicFont::set_size); ObjectTypeDB::bind_method(_MD("get_size"),&DynamicFont::get_size); + ObjectTypeDB::bind_method(_MD("set_use_mipmaps","enable"),&DynamicFont::set_use_mipmaps); + ObjectTypeDB::bind_method(_MD("get_use_mipmaps"),&DynamicFont::get_use_mipmaps); + ObjectTypeDB::bind_method(_MD("set_use_filter","enable"),&DynamicFont::set_use_filter); + ObjectTypeDB::bind_method(_MD("get_use_filter"),&DynamicFont::get_use_filter); + ObjectTypeDB::bind_method(_MD("set_spacing","type","value"),&DynamicFont::set_spacing); + ObjectTypeDB::bind_method(_MD("get_spacing","type"),&DynamicFont::get_spacing); + ObjectTypeDB::bind_method(_MD("add_fallback","data:DynamicFontData"),&DynamicFont::add_fallback); ObjectTypeDB::bind_method(_MD("set_fallback","idx","data:DynamicFontData"),&DynamicFont::set_fallback); ObjectTypeDB::bind_method(_MD("get_fallback:DynamicFontData","idx"),&DynamicFont::get_fallback); @@ -802,12 +900,26 @@ void DynamicFont::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT,"font/size"),_SCS("set_size"),_SCS("get_size")); + ADD_PROPERTYINZ(PropertyInfo(Variant::INT,"extra_spacing/top"),_SCS("set_spacing"),_SCS("get_spacing"),SPACING_TOP); + ADD_PROPERTYINZ(PropertyInfo(Variant::INT,"extra_spacing/bottom"),_SCS("set_spacing"),_SCS("get_spacing"),SPACING_BOTTOM); + ADD_PROPERTYINZ(PropertyInfo(Variant::INT,"extra_spacing/char"),_SCS("set_spacing"),_SCS("get_spacing"),SPACING_CHAR); + ADD_PROPERTYINZ(PropertyInfo(Variant::INT,"extra_spacing/space"),_SCS("set_spacing"),_SCS("get_spacing"),SPACING_SPACE); + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"font/use_mipmaps"),_SCS("set_use_mipmaps"),_SCS("get_use_mipmaps")); + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"font/use_filter"),_SCS("set_use_filter"),_SCS("get_use_filter")); ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"font/font",PROPERTY_HINT_RESOURCE_TYPE,"DynamicFontData"),_SCS("set_font_data"),_SCS("get_font_data")); + + BIND_CONSTANT( SPACING_TOP ); + BIND_CONSTANT( SPACING_BOTTOM ); + BIND_CONSTANT( SPACING_CHAR ); + BIND_CONSTANT( SPACING_SPACE ); } DynamicFont::DynamicFont() { - size=16; + spacing_top=0; + spacing_bottom=0; + spacing_char=0; + spacing_space=0; } DynamicFont::~DynamicFont() { diff --git a/scene/resources/dynamic_font.h b/scene/resources/dynamic_font.h index 9ad1b4edbf..4ae58ab0dd 100644 --- a/scene/resources/dynamic_font.h +++ b/scene/resources/dynamic_font.h @@ -45,21 +45,32 @@ class DynamicFontData : public Resource { OBJ_TYPE(DynamicFontData,Resource); +public: + + struct CacheID{ + + int size; + bool mipmaps; + bool filter; + + bool operator< (CacheID right) const; + CacheID() { size=16; mipmaps=false; filter=false; } + }; +private: const uint8_t *font_mem; int font_mem_size; bool force_autohinter; String font_path; - Map<int,DynamicFontAtSize*> size_cache; + Map<CacheID,DynamicFontAtSize*> size_cache; friend class DynamicFontAtSize; friend class DynamicFont; - - Ref<DynamicFontAtSize> _get_dynamic_font_at_size(int p_size); + Ref<DynamicFontAtSize> _get_dynamic_font_at_size(CacheID p_cache); protected: static void _bind_methods(); @@ -90,6 +101,8 @@ class DynamicFontAtSize : public Reference { int linegap; int rect_margin; + uint32_t texture_flags; + bool valid; struct CharTexture { @@ -124,7 +137,7 @@ class DynamicFontAtSize : public Reference { friend class DynamicFontData; Ref<DynamicFontData> font; - int size; + DynamicFontData::CacheID id; @@ -145,7 +158,7 @@ public: float draw_char(RID p_canvas_item, const Point2& p_pos, CharType p_char,CharType p_next,const Color& p_modulate,const Vector<Ref<DynamicFontAtSize> >& p_fallbacks) const; - + void set_texture_flags(uint32_t p_flags); DynamicFontAtSize(); ~DynamicFontAtSize(); @@ -157,18 +170,35 @@ class DynamicFont : public Font { OBJ_TYPE( DynamicFont, Font ); - Ref<DynamicFontData> data; +public: + + enum SpacingType{ + SPACING_TOP, + SPACING_BOTTOM, + SPACING_CHAR, + SPACING_SPACE + }; + +private: + + Ref<DynamicFontData> data; Ref<DynamicFontAtSize> data_at_size; Vector< Ref<DynamicFontData> > fallbacks; Vector< Ref<DynamicFontAtSize> > fallback_data_at_size; - int size; + DynamicFontData::CacheID cache_id; bool valid; + int spacing_top; + int spacing_bottom; + int spacing_char; + int spacing_space; protected: + void _reload_cache(); + bool _set(const StringName& p_name, const Variant& p_value); bool _get(const StringName& p_name,Variant &r_ret) const; void _get_property_list( List<PropertyInfo> *p_list) const; @@ -183,6 +213,14 @@ public: void set_size(int p_size); int get_size() const; + bool get_use_mipmaps() const; + void set_use_mipmaps(bool p_enable); + + bool get_use_filter() const; + void set_use_filter(bool p_enable); + + int get_spacing(int p_type) const; + void set_spacing(int p_type, int p_value); void add_fallback(const Ref<DynamicFontData>& p_data); void set_fallback(int p_idx,const Ref<DynamicFontData>& p_data); 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 f6213f74e8..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(); diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index c36480420b..f16d68a521 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -732,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 both are out, ignore connection - if (src_is_out && dst_is_out) { + + 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 (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; @@ -760,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 @@ -778,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 @@ -819,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; } } @@ -1478,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); @@ -1494,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; } @@ -1505,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 3b6c0898e0..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); diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp index 95645107d4..615c092dad 100644 --- a/scene/resources/scene_format_text.cpp +++ b/scene/resources/scene_format_text.cpp @@ -404,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); } @@ -1287,6 +1289,10 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path,const RES& p_re } internal_resources[res]=idx; +#ifdef TOOLS_ENABLED + res->set_edited(false); +#endif + } diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp index 8580ffdc5a..59246dfabe 100644 --- a/scene/resources/style_box.cpp +++ b/scene/resources/style_box.cpp @@ -141,7 +141,7 @@ void StyleBoxTexture::draw(RID p_canvas_item,const Rect2& p_rect) const { r.pos.y-=expand_margin[MARGIN_TOP]; r.size.x+=expand_margin[MARGIN_LEFT]+expand_margin[MARGIN_RIGHT]; r.size.y+=expand_margin[MARGIN_TOP]+expand_margin[MARGIN_BOTTOM]; - VisualServer::get_singleton()->canvas_item_add_style_box( p_canvas_item,r,region_rect,texture->get_rid(),Vector2(margin[MARGIN_LEFT],margin[MARGIN_TOP]),Vector2(margin[MARGIN_RIGHT],margin[MARGIN_BOTTOM]),draw_center); + VisualServer::get_singleton()->canvas_item_add_style_box( p_canvas_item,r,region_rect,texture->get_rid(),Vector2(margin[MARGIN_LEFT],margin[MARGIN_TOP]),Vector2(margin[MARGIN_RIGHT],margin[MARGIN_BOTTOM]),draw_center,modulate); } void StyleBoxTexture::set_draw_center(bool p_draw) { @@ -193,6 +193,19 @@ Rect2 StyleBoxTexture::get_region_rect() const { } +void StyleBoxTexture::set_modulate(const Color& p_modulate) { + if (modulate==p_modulate) + return; + modulate=p_modulate; + emit_changed(); +} + +Color StyleBoxTexture::get_modulate() const { + + return modulate; +} + + void StyleBoxTexture::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_texture","texture:Texture"),&StyleBoxTexture::set_texture); @@ -210,6 +223,10 @@ void StyleBoxTexture::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_draw_center","enable"),&StyleBoxTexture::set_draw_center); ObjectTypeDB::bind_method(_MD("get_draw_center"),&StyleBoxTexture::get_draw_center); + ObjectTypeDB::bind_method(_MD("set_modulate","color"),&StyleBoxTexture::set_modulate); + ObjectTypeDB::bind_method(_MD("get_modulate"),&StyleBoxTexture::get_modulate); + + ADD_SIGNAL(MethodInfo("texture_changed")); ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture" ), _SCS("set_texture"),_SCS("get_texture") ); @@ -222,6 +239,7 @@ void StyleBoxTexture::_bind_methods() { ADD_PROPERTYI( PropertyInfo( Variant::REAL, "expand_margin/right", PROPERTY_HINT_RANGE,"0,2048,1" ), _SCS("set_expand_margin_size"),_SCS("get_expand_margin_size"), MARGIN_RIGHT ); ADD_PROPERTYI( PropertyInfo( Variant::REAL, "expand_margin/top", PROPERTY_HINT_RANGE,"0,2048,1" ), _SCS("set_expand_margin_size"),_SCS("get_expand_margin_size"), MARGIN_TOP ); ADD_PROPERTYI( PropertyInfo( Variant::REAL, "expand_margin/bottom", PROPERTY_HINT_RANGE,"0,2048,1" ), _SCS("set_expand_margin_size"),_SCS("get_expand_margin_size"), MARGIN_BOTTOM ); + ADD_PROPERTY( PropertyInfo( Variant::COLOR, "modulate/color" ), _SCS("set_modulate"),_SCS("get_modulate")); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "draw_center" ) , _SCS("set_draw_center"),_SCS("get_draw_center")); } @@ -234,6 +252,7 @@ StyleBoxTexture::StyleBoxTexture() { expand_margin[i]=0; } draw_center=true; + modulate=Color(1,1,1,1); } StyleBoxTexture::~StyleBoxTexture() { diff --git a/scene/resources/style_box.h b/scene/resources/style_box.h index 98aaee754b..f667318e24 100644 --- a/scene/resources/style_box.h +++ b/scene/resources/style_box.h @@ -84,6 +84,7 @@ class StyleBoxTexture : public StyleBox { Rect2 region_rect; Ref<Texture> texture; bool draw_center; + Color modulate; protected: @@ -109,6 +110,9 @@ public: bool get_draw_center() const; virtual Size2 get_center_size() const; + void set_modulate(const Color& p_modulate); + Color get_modulate() const; + virtual void draw(RID p_canvas_item,const Rect2& p_rect) const; 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/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..4c963da5b4 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()) { @@ -374,7 +407,7 @@ World2D::World2D() { Physics2DServer::get_singleton()->area_set_param(space,Physics2DServer::AREA_PARAM_GRAVITY,GLOBAL_DEF("physics_2d/default_gravity",98)); Physics2DServer::get_singleton()->area_set_param(space,Physics2DServer::AREA_PARAM_GRAVITY_VECTOR,GLOBAL_DEF("physics_2d/default_gravity_vector",Vector2(0,1))); // TODO: Remove this deprecation warning and compatibility code for 2.2 or 3.0 - if (Globals::get_singleton()->get("physics_2d/default_density") && !Globals::get_singleton()->get("physics_2d/default_linear_damp)")) { + if (Globals::get_singleton()->get("physics_2d/default_density") && !Globals::get_singleton()->get("physics_2d/default_linear_damp")) { WARN_PRINT("Deprecated parameter 'physics_2d/default_density'. It was renamed to 'physics_2d/default_linear_damp', adjusting your project settings accordingly (make sure to adjust scripts that potentially rely on 'physics_2d/default_density'."); Globals::get_singleton()->set("physics_2d/default_linear_damp", Globals::get_singleton()->get("physics_2d/default_density")); Globals::get_singleton()->set_persisting("physics_2d/default_linear_damp", true); |