diff options
Diffstat (limited to 'scene/gui')
31 files changed, 1166 insertions, 163 deletions
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index 3bcc60b86a..2200cac5da 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -289,7 +289,7 @@ void BaseButton::set_disabled(bool p_disabled) { if (p_disabled) set_focus_mode(FOCUS_NONE); else - set_focus_mode(FOCUS_ALL); + set_focus_mode(enabled_focus_mode); } bool BaseButton::is_disabled() const { @@ -377,12 +377,56 @@ bool BaseButton::get_click_on_press() const { return status.click_on_press; } +void BaseButton::set_enabled_focus_mode(FocusMode p_mode) { + enabled_focus_mode = p_mode; + if (!status.disabled) { + set_focus_mode( p_mode ); + } +} + +Control::FocusMode BaseButton::get_enabled_focus_mode() const { + + return enabled_focus_mode; +} + +void BaseButton::set_shortcut(const Ref<ShortCut>& p_shortcut) { + + if (shortcut.is_null() == p_shortcut.is_null()) + return; + + shortcut=p_shortcut; + set_process_unhandled_input(shortcut.is_valid()); +} +Ref<ShortCut> BaseButton:: get_shortcut() const { + return shortcut; +} + +void BaseButton::_unhandled_input(InputEvent p_event) { + + if (!is_disabled() && is_visible() && shortcut.is_valid() && shortcut->is_shortcut(p_event)) { + if (is_toggle_mode()) { + set_pressed(!is_pressed()); + emit_signal("toggled",is_pressed()); + } + + emit_signal("pressed"); + } +} + +String BaseButton::get_tooltip(const Point2& p_pos) const { + + String tooltip=Control::get_tooltip(p_pos); + if (shortcut.is_valid() && shortcut->is_valid()) + tooltip+=" ("+shortcut->get_as_text()+")"; + return tooltip; +} void BaseButton::_bind_methods() { ObjectTypeDB::bind_method(_MD("_input_event"),&BaseButton::_input_event); + ObjectTypeDB::bind_method(_MD("_unhandled_input"),&BaseButton::_unhandled_input); ObjectTypeDB::bind_method(_MD("set_pressed","pressed"),&BaseButton::set_pressed); ObjectTypeDB::bind_method(_MD("is_pressed"),&BaseButton::is_pressed); ObjectTypeDB::bind_method(_MD("is_hovered"),&BaseButton::is_hovered); @@ -393,6 +437,10 @@ void BaseButton::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_click_on_press","enable"),&BaseButton::set_click_on_press); ObjectTypeDB::bind_method(_MD("get_click_on_press"),&BaseButton::get_click_on_press); ObjectTypeDB::bind_method(_MD("get_draw_mode"),&BaseButton::get_draw_mode); + ObjectTypeDB::bind_method(_MD("set_enabled_focus_mode","mode"),&BaseButton::set_enabled_focus_mode); + ObjectTypeDB::bind_method(_MD("get_enabled_focus_mode"),&BaseButton::get_enabled_focus_mode); + ObjectTypeDB::bind_method(_MD("set_shortcut","shortcut"),&BaseButton::set_shortcut); + ObjectTypeDB::bind_method(_MD("get_shortcut"),&BaseButton::get_shortcut); BIND_VMETHOD(MethodInfo("_pressed")); BIND_VMETHOD(MethodInfo("_toggled",PropertyInfo(Variant::BOOL,"pressed"))); @@ -404,6 +452,8 @@ void BaseButton::_bind_methods() { ADD_PROPERTY( PropertyInfo( Variant::BOOL, "toggle_mode"), _SCS("set_toggle_mode"), _SCS("is_toggle_mode")); ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "is_pressed"), _SCS("set_pressed"), _SCS("is_pressed")); ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "click_on_press"), _SCS("set_click_on_press"), _SCS("get_click_on_press")); + ADD_PROPERTY( PropertyInfo( Variant::INT,"enabled_focus_mode", PROPERTY_HINT_ENUM, "None,Click,All" ), _SCS("set_enabled_focus_mode"), _SCS("get_enabled_focus_mode") ); + ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "shortcut",PROPERTY_HINT_RESOURCE_TYPE,"ShortCut"), _SCS("set_shortcut"), _SCS("get_shortcut")); BIND_CONSTANT( DRAW_NORMAL ); @@ -424,6 +474,7 @@ BaseButton::BaseButton() { status.click_on_press=false; status.pressing_button=0; set_focus_mode( FOCUS_ALL ); + enabled_focus_mode = FOCUS_ALL; group=NULL; diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h index 9a5213d971..0056b00f33 100644 --- a/scene/gui/base_button.h +++ b/scene/gui/base_button.h @@ -42,6 +42,8 @@ class BaseButton : public Control { OBJ_TYPE( BaseButton, Control ); bool toggle_mode; + FocusMode enabled_focus_mode; + Ref<ShortCut> shortcut; struct Status { @@ -56,6 +58,7 @@ class BaseButton : public Control { } status; + ButtonGroup *group; @@ -68,6 +71,7 @@ protected: virtual void toggled(bool p_pressed); static void _bind_methods(); virtual void _input_event(InputEvent p_event); + virtual void _unhandled_input(InputEvent p_event); void _notification(int p_what); public: @@ -97,6 +101,13 @@ public: void set_click_on_press(bool p_click_on_press); bool get_click_on_press() const; + void set_enabled_focus_mode(FocusMode p_mode); + FocusMode get_enabled_focus_mode() const; + + void set_shortcut(const Ref<ShortCut>& p_shortcut); + Ref<ShortCut> get_shortcut() const; + + virtual String get_tooltip(const Point2& p_pos) const; BaseButton(); ~BaseButton(); diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp index a9522cf248..a6ffc30a83 100644 --- a/scene/gui/box_container.cpp +++ b/scene/gui/box_container.cpp @@ -280,6 +280,7 @@ BoxContainer::AlignMode BoxContainer::get_alignment() const { void BoxContainer::add_spacer(bool p_begin) { Control *c = memnew( Control ); + c->set_stop_mouse(false); if (vertical) c->set_v_size_flags(SIZE_EXPAND_FILL); else diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp index 0f1622a838..579f6e08c9 100644 --- a/scene/gui/button.cpp +++ b/scene/gui/button.cpp @@ -213,7 +213,6 @@ Button::TextAlign Button::get_text_align() const { return align; } - void Button::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_text","text"),&Button::set_text); diff --git a/scene/gui/button.h b/scene/gui/button.h index 8a17a164a0..c39237c9af 100644 --- a/scene/gui/button.h +++ b/scene/gui/button.h @@ -54,7 +54,6 @@ private: TextAlign align; - protected: virtual Size2 get_minimum_size() const; @@ -62,6 +61,8 @@ protected: static void _bind_methods(); public: // + + void set_text(const String& p_text); String get_text() const; @@ -77,6 +78,7 @@ public: void set_text_align(TextAlign p_align); TextAlign get_text_align() const; + Button(const String& p_text=String()); ~Button(); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 73e7237058..bd56369746 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -770,7 +770,7 @@ Size2 Control::get_minimum_size() const { Ref<Texture> Control::get_icon(const StringName& p_name,const StringName& p_type) const { - if (p_type==StringName()) { + if (p_type==StringName() || p_type=="") { const Ref<Texture>* tex = data.icon_override.getptr(p_name); if (tex) @@ -800,7 +800,7 @@ Ref<Texture> Control::get_icon(const StringName& p_name,const StringName& p_type } Ref<Shader> Control::get_shader(const StringName& p_name,const StringName& p_type) const { - if (p_type==StringName()) { + if (p_type==StringName() || p_type=="") { const Ref<Shader>* sdr = data.shader_override.getptr(p_name); if (sdr) @@ -830,7 +830,7 @@ Ref<Shader> Control::get_shader(const StringName& p_name,const StringName& p_typ Ref<StyleBox> Control::get_stylebox(const StringName& p_name,const StringName& p_type) const { - if (p_type==StringName()) { + if (p_type==StringName() || p_type=="") { const Ref<StyleBox>* style = data.style_override.getptr(p_name); if (style) return *style; @@ -858,7 +858,7 @@ Ref<StyleBox> Control::get_stylebox(const StringName& p_name,const StringName& p } Ref<Font> Control::get_font(const StringName& p_name,const StringName& p_type) const { - if (p_type==StringName()) { + if (p_type==StringName() || p_type=="") { const Ref<Font>* font = data.font_override.getptr(p_name); if (font) return *font; @@ -889,7 +889,7 @@ Ref<Font> Control::get_font(const StringName& p_name,const StringName& p_type) c } Color Control::get_color(const StringName& p_name,const StringName& p_type) const { - if (p_type==StringName()) { + if (p_type==StringName() || p_type=="") { const Color* color = data.color_override.getptr(p_name); if (color) return *color; @@ -918,7 +918,7 @@ Color Control::get_color(const StringName& p_name,const StringName& p_type) cons int Control::get_constant(const StringName& p_name,const StringName& p_type) const { - if (p_type==StringName()) { + if (p_type==StringName() || p_type=="") { const int* constant = data.constant_override.getptr(p_name); if (constant) return *constant; @@ -946,12 +946,64 @@ int Control::get_constant(const StringName& p_name,const StringName& p_type) con } +bool Control::has_icon_override(const StringName& p_name) const { + + const Ref<Texture>* tex = data.icon_override.getptr(p_name); + if (tex) + return true; + else + return false; +} + +bool Control::has_shader_override(const StringName &p_name) const { + + const Ref<Shader>* sdr = data.shader_override.getptr(p_name); + if (sdr) + return true; + else + return false; +} + +bool Control::has_stylebox_override(const StringName& p_name) const { + + const Ref<StyleBox>* style = data.style_override.getptr(p_name); + if (style) + return true; + else + return false; +} + +bool Control::has_font_override(const StringName& p_name) const { + + const Ref<Font>* font = data.font_override.getptr(p_name); + if (font) + return true; + else + return false; +} + +bool Control::has_color_override(const StringName& p_name) const { + + const Color* color = data.color_override.getptr(p_name); + if (color) + return true; + else + return false; +} + +bool Control::has_constant_override(const StringName& p_name) const { + + const int* constant = data.constant_override.getptr(p_name); + if (constant) + return true; + else + return false; +} bool Control::has_icon(const StringName& p_name,const StringName& p_type) const { - if (p_type==StringName()) { - const Ref<Texture>* tex = data.icon_override.getptr(p_name); - if (tex) + if (p_type==StringName() || p_type=="") { + if (has_icon_override(p_name) == true) return true; } @@ -977,11 +1029,10 @@ bool Control::has_icon(const StringName& p_name,const StringName& p_type) const } -bool Control::has_shader(const StringName &p_name, const StringName &p_type) const -{ - if (p_type==StringName()) { - const Ref<Shader>* sdr = data.shader_override.getptr(p_name); - if (sdr) +bool Control::has_shader(const StringName &p_name, const StringName &p_type) const { + + if (p_type==StringName() || p_type=="") { + if (has_shader_override(p_name)==true) return true; } @@ -1008,10 +1059,8 @@ bool Control::has_shader(const StringName &p_name, const StringName &p_type) con } bool Control::has_stylebox(const StringName& p_name,const StringName& p_type) const { - if (p_type==StringName()) { - const Ref<StyleBox>* style = data.style_override.getptr(p_name); - - if (style) + if (p_type==StringName() || p_type=="") { + if (has_stylebox_override(p_name)==true) return true; } @@ -1038,9 +1087,8 @@ bool Control::has_stylebox(const StringName& p_name,const StringName& p_type) co } bool Control::has_font(const StringName& p_name,const StringName& p_type) const { - if (p_type==StringName()) { - const Ref<Font>* font = data.font_override.getptr(p_name); - if (font) + if (p_type==StringName() || p_type=="") { + if (has_font_override(p_name)==true) return true; } @@ -1066,11 +1114,11 @@ bool Control::has_font(const StringName& p_name,const StringName& p_type) const return Theme::get_default()->has_font( p_name, type ); } -bool Control::has_color(const StringName& p_name,const StringName& p_type) const { - if (p_type==StringName()) { - const Color* color = data.color_override.getptr(p_name); - if (color) +bool Control::has_color(const StringName& p_name, const StringName& p_type) const { + + if (p_type==StringName() || p_type=="") { + if (has_color_override(p_name)==true) return true; } @@ -1098,10 +1146,8 @@ bool Control::has_color(const StringName& p_name,const StringName& p_type) const bool Control::has_constant(const StringName& p_name,const StringName& p_type) const { - if (p_type==StringName()) { - - const int* constant = data.constant_override.getptr(p_name); - if (constant) + if (p_type==StringName() || p_type=="") { + if (has_constant_override(p_name) == true) return true; } @@ -1810,6 +1856,7 @@ void Control::_propagate_theme_changed(Control *p_owner) { void Control::set_theme(const Ref<Theme>& p_theme) { + data.theme=p_theme; if (!p_theme.is_null()) { @@ -2265,6 +2312,7 @@ void Control::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_area_as_parent_rect","margin"),&Control::set_area_as_parent_rect,DEFVAL(0)); ObjectTypeDB::bind_method(_MD("show_modal","exclusive"),&Control::show_modal,DEFVAL(false)); ObjectTypeDB::bind_method(_MD("set_focus_mode","mode"),&Control::set_focus_mode); + ObjectTypeDB::bind_method(_MD("get_focus_mode"),&Control::get_focus_mode); ObjectTypeDB::bind_method(_MD("has_focus"),&Control::has_focus); ObjectTypeDB::bind_method(_MD("grab_focus"),&Control::grab_focus); ObjectTypeDB::bind_method(_MD("release_focus"),&Control::release_focus); @@ -2295,6 +2343,17 @@ void Control::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_color","name","type"),&Control::get_color,DEFVAL("")); ObjectTypeDB::bind_method(_MD("get_constant","name","type"),&Control::get_constant,DEFVAL("")); + ObjectTypeDB::bind_method(_MD("has_icon_override", "name"), &Control::has_icon_override); + ObjectTypeDB::bind_method(_MD("has_stylebox_override", "name"), &Control::has_stylebox_override); + ObjectTypeDB::bind_method(_MD("has_font_override", "name"), &Control::has_font_override); + ObjectTypeDB::bind_method(_MD("has_color_override", "name"), &Control::has_color_override); + ObjectTypeDB::bind_method(_MD("has_constant_override", "name"), &Control::has_constant_override); + + ObjectTypeDB::bind_method(_MD("has_icon", "name", "type"), &Control::has_icon, DEFVAL("")); + ObjectTypeDB::bind_method(_MD("has_stylebox", "name", "type"), &Control::has_stylebox, DEFVAL("")); + ObjectTypeDB::bind_method(_MD("has_font", "name", "type"), &Control::has_font, DEFVAL("")); + ObjectTypeDB::bind_method(_MD("has_color", "name", "type"), &Control::has_color, DEFVAL("")); + ObjectTypeDB::bind_method(_MD("has_constant", "name", "type"), &Control::has_constant, DEFVAL("")); ObjectTypeDB::bind_method(_MD("get_parent_control:Control"),&Control::get_parent_control); @@ -2324,6 +2383,7 @@ void Control::_bind_methods() { ObjectTypeDB::bind_method(_MD("warp_mouse","to_pos"),&Control::warp_mouse); + ObjectTypeDB::bind_method(_MD("minimum_size_changed"), &Control::minimum_size_changed); BIND_VMETHOD(MethodInfo("_input_event",PropertyInfo(Variant::INPUT_EVENT,"event"))); BIND_VMETHOD(MethodInfo(Variant::VECTOR2,"get_minimum_size")); diff --git a/scene/gui/control.h b/scene/gui/control.h index f720185c9d..59704ae29b 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -35,7 +35,7 @@ #include "scene/2d/canvas_item.h" #include "math_2d.h" #include "rid.h" - +#include "scene/gui/input_action.h" /** @author Juan Linietsky <reduzio@gmail.com> */ @@ -341,6 +341,13 @@ public: Color get_color(const StringName& p_name,const StringName& p_type=StringName()) const; int get_constant(const StringName& p_name,const StringName& p_type=StringName()) const; + bool has_icon_override(const StringName& p_name) const; + bool has_shader_override(const StringName& p_name) const; + bool has_stylebox_override(const StringName& p_name) const; + bool has_font_override(const StringName& p_name) const; + bool has_color_override(const StringName& p_name) const; + bool has_constant_override(const StringName& p_name) const; + bool has_icon(const StringName& p_name,const StringName& p_type=StringName()) const; bool has_shader(const StringName& p_name,const StringName& p_type=StringName()) const; bool has_stylebox(const StringName& p_name,const StringName& p_type=StringName()) const; diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index 51242d89bd..6342391383 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -118,6 +118,16 @@ void WindowDialog::set_title(const String& p_title) { update(); } +Size2 WindowDialog::get_minimum_size() const { + + Ref<Font> font = get_font("title_font","WindowDialog"); + int msx=close_button->get_combined_minimum_size().x; + msx+=font->get_string_size(title).x; + + return Size2(msx,1); +} + + String WindowDialog::get_title() const { return title; @@ -192,11 +202,9 @@ void AcceptDialog::_notification(int p_what) { if (p_what==NOTIFICATION_MODAL_CLOSE) { cancel_pressed(); - } if (p_what==NOTIFICATION_DRAW) { - - - + } if (p_what==NOTIFICATION_RESIZED) { + _update_child_rect(); } } @@ -244,12 +252,69 @@ void AcceptDialog::register_text_enter(Node *p_line_edit) { p_line_edit->connect("text_entered", this,"_builtin_text_entered"); } +void AcceptDialog::_update_child_rect() { + + int margin = get_constant("margin","Dialogs"); + Size2 size = get_size(); + Size2 hminsize = hbc->get_combined_minimum_size(); + + Vector2 cpos(margin,margin); + Vector2 csize(size.x-margin*2,size.y-margin*3-hminsize.y); + label->set_pos(cpos); + label->set_size(csize); + + if (child) { + + child->set_pos(cpos); + child->set_size(csize); + } + + cpos.y+=csize.y+margin; + csize.y=hminsize.y; + + hbc->set_pos(cpos); + hbc->set_size(csize); + +} + +Size2 AcceptDialog::get_minimum_size() const { + + int margin = get_constant("margin","Dialogs"); + Size2 minsize = label->get_combined_minimum_size(); + if (child) { + + Size2 cminsize = child->get_combined_minimum_size(); + minsize.x=MAX(cminsize.x,minsize.x); + minsize.y=MAX(cminsize.y,minsize.y); + } + + Size2 hminsize = hbc->get_combined_minimum_size(); + minsize.x = MAX(hminsize.x,minsize.x); + minsize.y+=hminsize.y; + minsize.x+=margin*2; + minsize.y+=margin*3; //one as separation between hbc and child + + Size2 wmsize = WindowDialog::get_minimum_size(); + minsize.x=MAX(wmsize.x,minsize.x); + return minsize; +} + + void AcceptDialog::set_child_rect(Control *p_child) { ERR_FAIL_COND(p_child->get_parent()!=this); - p_child->set_area_as_parent_rect(get_constant("margin","Dialogs")); - p_child->set_margin(MARGIN_BOTTOM, get_constant("button_margin","Dialogs")+10); + //p_child->set_area_as_parent_rect(get_constant("margin","Dialogs")); + child=p_child; + minimum_size_changed(); + _update_child_rect(); +} + +void AcceptDialog::remove_child_notify(Node *p_child) { + + if (p_child==child) { + child=NULL; + } } void AcceptDialog::_custom_action(const String& p_action) { @@ -284,7 +349,7 @@ Button* AcceptDialog::add_cancel(const String &p_cancel) { String c = p_cancel; if (p_cancel=="") - c="Cancel"; + c=RTR("Cancel"); Button *b = swap_ok_cancel ? add_button(c,true) : add_button(c); b->connect("pressed",this,"_closed"); return b; @@ -341,7 +406,7 @@ AcceptDialog::AcceptDialog() { hbc->add_spacer(); ok = memnew( Button ); - ok->set_text("OK"); + ok->set_text(RTR("OK")); hbc->add_child(ok); hbc->add_spacer(); //add_child(ok); @@ -351,7 +416,9 @@ AcceptDialog::AcceptDialog() { set_as_toplevel(true); hide_on_ok=true; - set_title("Alert!"); + set_title(RTR("Alert!")); + + child=NULL; } @@ -372,6 +439,6 @@ Button *ConfirmationDialog::get_cancel() { ConfirmationDialog::ConfirmationDialog() { - set_title("Please Confirm..."); + set_title(RTR("Please Confirm...")); cancel = add_cancel(); } diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h index f256c49aee..d00bb41ff6 100644 --- a/scene/gui/dialogs.h +++ b/scene/gui/dialogs.h @@ -64,6 +64,8 @@ public: void set_title(const String& p_title); String get_title() const; + Size2 get_minimum_size() const; + WindowDialog(); ~WindowDialog(); @@ -89,6 +91,7 @@ class AcceptDialog : public WindowDialog { OBJ_TYPE(AcceptDialog,WindowDialog); + Control *child; HBoxContainer *hbc; Label *label; Button *ok; @@ -100,10 +103,12 @@ class AcceptDialog : public WindowDialog { void _ok_pressed(); void _close_pressed(); void _builtin_text_entered(const String& p_text); + void _update_child_rect(); static bool swap_ok_cancel; + virtual void remove_child_notify(Node *p_child); protected: @@ -116,6 +121,8 @@ protected: virtual void custom_action(const String&) {} public: + Size2 get_minimum_size() const; + Label *get_label() { return label; } static void set_swap_ok_cancel(bool p_swap); diff --git a/scene/gui/input_action.cpp b/scene/gui/input_action.cpp new file mode 100644 index 0000000000..c4e7a75298 --- /dev/null +++ b/scene/gui/input_action.cpp @@ -0,0 +1,125 @@ +#include "input_action.h" +#include "os/keyboard.h" + +void ShortCut::set_shortcut(const InputEvent& p_shortcut){ + + shortcut=p_shortcut; + emit_changed(); +} + +InputEvent ShortCut::get_shortcut() const{ + + return shortcut; +} + +bool ShortCut::is_shortcut(const InputEvent& p_event) const { + + bool same=false; + + + switch(p_event.type) { + + case InputEvent::KEY: { + + same=(shortcut.key.scancode==p_event.key.scancode && shortcut.key.mod == p_event.key.mod); + + } break; + case InputEvent::JOYSTICK_BUTTON: { + + same=(shortcut.joy_button.button_index==p_event.joy_button.button_index); + + } break; + case InputEvent::MOUSE_BUTTON: { + + same=(shortcut.mouse_button.button_index==p_event.mouse_button.button_index); + + } break; + case InputEvent::JOYSTICK_MOTION: { + + same=(shortcut.joy_motion.axis==p_event.joy_motion.axis && (shortcut.joy_motion.axis_value < 0) == (p_event.joy_motion.axis_value < 0)); + + } break; + default: {}; + } + + return same; +} + +String ShortCut::get_as_text() const { + + switch(shortcut.type) { + + case InputEvent::NONE: { + + return "None"; + } break; + case InputEvent::KEY: { + + String str; + if (shortcut.key.mod.shift) + str+=RTR("Shift+"); + if (shortcut.key.mod.alt) + str+=RTR("Alt+"); + if (shortcut.key.mod.control) + str+=RTR("Ctrl+"); + if (shortcut.key.mod.meta) + str+=RTR("Meta+"); + + str+=keycode_get_string(shortcut.key.scancode).capitalize(); + + return str; + } break; + case InputEvent::JOYSTICK_BUTTON: { + + String str = RTR("Device")+" "+itos(shortcut.device)+", "+RTR("Button")+" "+itos(shortcut.joy_button.button_index); + str+="."; + + return str; + } break; + case InputEvent::MOUSE_BUTTON: { + + String str = RTR("Device")+" "+itos(shortcut.device)+", "; + switch (shortcut.mouse_button.button_index) { + case BUTTON_LEFT: str+=RTR("Left Button."); break; + case BUTTON_RIGHT: str+=RTR("Right Button."); break; + case BUTTON_MIDDLE: str+=RTR("Middle Button."); break; + case BUTTON_WHEEL_UP: str+=RTR("Wheel Up."); break; + case BUTTON_WHEEL_DOWN: str+=RTR("Wheel Down."); break; + default: str+=RTR("Button")+" "+itos(shortcut.mouse_button.button_index)+"."; + } + + return str; + } break; + case InputEvent::JOYSTICK_MOTION: { + + int ax = shortcut.joy_motion.axis; + String str = RTR("Device")+" "+itos(shortcut.device)+", "+RTR("Axis")+" "+itos(ax)+"."; + + return str; + } break; + } + + return ""; +} + +bool ShortCut::is_valid() const { + + return shortcut.type!=InputEvent::NONE; +} + +void ShortCut::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_shortcut","event"),&ShortCut::set_shortcut); + ObjectTypeDB::bind_method(_MD("get_shortcut"),&ShortCut::get_shortcut); + + ObjectTypeDB::bind_method(_MD("is_valid"),&ShortCut::is_valid); + + ObjectTypeDB::bind_method(_MD("is_shortcut","event"),&ShortCut::is_shortcut); + ObjectTypeDB::bind_method(_MD("get_as_text"),&ShortCut::get_as_text); + + ADD_PROPERTY(PropertyInfo(Variant::INPUT_EVENT,"shortcut"),_SCS("set_shortcut"),_SCS("get_shortcut")); +} + +ShortCut::ShortCut(){ + +} diff --git a/scene/gui/input_action.h b/scene/gui/input_action.h new file mode 100644 index 0000000000..8e0e1ef0bd --- /dev/null +++ b/scene/gui/input_action.h @@ -0,0 +1,26 @@ +#ifndef INPUTACTION_H +#define INPUTACTION_H + +#include "resource.h" + +class ShortCut : public Resource { + + OBJ_TYPE(ShortCut,Resource); + + InputEvent shortcut; +protected: + + static void _bind_methods(); +public: + + void set_shortcut(const InputEvent& p_shortcut); + InputEvent get_shortcut() const; + bool is_shortcut(const InputEvent& p_Event) const; + bool is_valid() const; + + String get_as_text() const; + + ShortCut(); +}; + +#endif // INPUTACTION_H diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index c1a0e43e49..fc4ab5f8ca 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -325,6 +325,18 @@ int ItemList::get_fixed_column_width() const{ return fixed_column_width; } +void ItemList::set_same_column_width(bool p_enable){ + + same_column_width=p_enable; + update(); + shape_changed=true; + +} +int ItemList::is_same_column_width() const{ + + return same_column_width; +} + void ItemList::set_max_text_lines(int p_lines){ ERR_FAIL_COND(p_lines<1); @@ -824,6 +836,8 @@ void ItemList::_notification(int p_what) { } if (shape_changed) { + + float max_column_width = 0; //1- compute item minimum sizes for(int i=0;i<items.size();i++) { @@ -831,7 +845,7 @@ void ItemList::_notification(int p_what) { Size2 minsize; if (items[i].icon.is_valid()) { - minsize=_adjust_to_max_size(items[i].get_icon_size(),max_icon_size); + minsize=_adjust_to_max_size(items[i].get_icon_size(),max_icon_size) * icon_scale; if (items[i].text!="") { if (icon_mode==ICON_MODE_TOP) { @@ -864,10 +878,11 @@ void ItemList::_notification(int p_what) { } - - items[i].rect_cache.size=minsize; if (fixed_column_width>0) - items[i].rect_cache.size.x=fixed_column_width; + minsize.x=fixed_column_width; + max_column_width=MAX(max_column_width,minsize.x); + items[i].rect_cache.size=minsize; + items[i].min_rect_cache.size=minsize; } @@ -896,17 +911,23 @@ void ItemList::_notification(int p_what) { break; } + items[i].rect_cache=items[i].min_rect_cache; + if(same_column_width) + items[i].rect_cache.size.x=max_column_width; items[i].rect_cache.pos=ofs; max_h=MAX(max_h,items[i].rect_cache.size.y); - ofs.x+=items[i].rect_cache.size.x; + ofs.x+=items[i].rect_cache.size.x + hseparation; //print_line("item "+itos(i)+" ofs "+rtos(items[i].rect_cache.size.x)); - if (col>0) - ofs.x+=hseparation; col++; if (col==current_columns) { 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; @@ -914,6 +935,10 @@ void ItemList::_notification(int p_what) { } } + for(int j=items.size()-1;j>=0 && col>0;j--, col--) { + items[j].rect_cache.size.y = max_h; + } + if (all_fit) { float max = MAX(page,ofs.y+max_h); scroll_bar->set_max(max); @@ -976,7 +1001,7 @@ void ItemList::_notification(int p_what) { Vector2 text_ofs; if (items[i].icon.is_valid()) { - Size2 icon_size = _adjust_to_max_size(items[i].get_icon_size(),max_icon_size); + Size2 icon_size = _adjust_to_max_size(items[i].get_icon_size(),max_icon_size) * icon_scale; Vector2 icon_ofs; if (min_icon_size!=Vector2()) { @@ -988,7 +1013,12 @@ void ItemList::_notification(int p_what) { if (icon_mode==ICON_MODE_TOP) { pos.x += Math::floor((items[i].rect_cache.size.width - icon_size.width)/2); + pos.y += MIN( + Math::floor((items[i].rect_cache.size.height - icon_size.height)/2), + items[i].rect_cache.size.height - items[i].min_rect_cache.size.height + ); text_ofs.y = MAX(icon_size.height, min_icon_size.y) + icon_margin; + text_ofs.y += items[i].rect_cache.size.height - items[i].min_rect_cache.size.height; } else { pos.y += Math::floor((items[i].rect_cache.size.height - icon_size.height)/2); @@ -1014,6 +1044,8 @@ void ItemList::_notification(int p_what) { Vector2 size = font->get_string_size(items[i].text); if (fixed_column_width) max_len=fixed_column_width; + else if(same_column_width) + max_len=items[i].rect_cache.size.x; else max_len=size.x; @@ -1201,6 +1233,14 @@ bool ItemList::get_allow_rmb_select() const { return allow_rmb_select; } +void ItemList::set_icon_scale(real_t p_scale) { + icon_scale = p_scale; +} + +real_t ItemList::get_icon_scale() const { + return icon_scale; +} + void ItemList::_bind_methods(){ ObjectTypeDB::bind_method(_MD("add_item","text","icon:Texture","selectable"),&ItemList::add_item,DEFVAL(Variant()),DEFVAL(true)); @@ -1243,6 +1283,9 @@ void ItemList::_bind_methods(){ 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); + ObjectTypeDB::bind_method(_MD("set_same_column_width","enable"),&ItemList::set_same_column_width); + ObjectTypeDB::bind_method(_MD("is_same_column_width"),&ItemList::is_same_column_width); + ObjectTypeDB::bind_method(_MD("set_max_text_lines","lines"),&ItemList::set_max_text_lines); ObjectTypeDB::bind_method(_MD("get_max_text_lines"),&ItemList::get_max_text_lines); @@ -1261,6 +1304,9 @@ void ItemList::_bind_methods(){ ObjectTypeDB::bind_method(_MD("set_max_icon_size","size"),&ItemList::set_max_icon_size); ObjectTypeDB::bind_method(_MD("get_max_icon_size"),&ItemList::get_max_icon_size); + ObjectTypeDB::bind_method(_MD("set_icon_scale","scale"),&ItemList::set_icon_scale); + ObjectTypeDB::bind_method(_MD("get_icon_scale"),&ItemList::get_icon_scale); + ObjectTypeDB::bind_method(_MD("set_allow_rmb_select","allow"),&ItemList::set_allow_rmb_select); ObjectTypeDB::bind_method(_MD("get_allow_rmb_select"),&ItemList::get_allow_rmb_select); @@ -1292,6 +1338,7 @@ ItemList::ItemList() { icon_mode=ICON_MODE_LEFT; fixed_column_width=0; + same_column_width = false; max_text_lines=1; max_columns=1; @@ -1308,6 +1355,7 @@ ItemList::ItemList() { defer_select_single=-1; allow_rmb_select=false; + icon_scale = 1.0f; } ItemList::~ItemList() { diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h index 59fa1d8270..087c585128 100644 --- a/scene/gui/item_list.h +++ b/scene/gui/item_list.h @@ -33,6 +33,7 @@ private: Color custom_bg; Rect2 rect_cache; + Rect2 min_rect_cache; Size2 get_icon_size() const; @@ -44,6 +45,7 @@ private: bool shape_changed; bool ensure_selected_visible; + bool same_column_width; Vector<Item> items; Vector<int> separators; @@ -59,12 +61,18 @@ private: int fixed_column_width; int max_text_lines; int max_columns; + Size2 min_icon_size; Size2 max_icon_size; + + Size2 max_item_size_cache; + int defer_select_single; bool allow_rmb_select; + real_t icon_scale; + void _scroll_changed(double); void _input_event(const InputEvent& p_event); protected: @@ -121,6 +129,9 @@ public: void set_fixed_column_width(int p_size); int get_fixed_column_width() const; + void set_same_column_width(bool p_enable); + int is_same_column_width() const; + void set_max_text_lines(int p_amount); int get_max_text_lines() const; @@ -150,6 +161,9 @@ public: virtual String get_tooltip(const Point2& p_pos) const; int get_item_at_pos(const Point2& p_pos,bool p_exact=false) const; + void set_icon_scale(real_t p_scale); + real_t get_icon_scale() const; + ItemList(); ~ItemList(); }; diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index e8097c79a4..09c6a77b42 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -87,10 +87,11 @@ void Label::_notification(int p_what) { Color font_color_shadow = get_color("font_color_shadow"); bool use_outlinde = get_constant("shadow_as_outline"); Point2 shadow_ofs(get_constant("shadow_offset_x"),get_constant("shadow_offset_y")); + int line_spacing = get_constant("line_spacing"); VisualServer::get_singleton()->canvas_item_set_distance_field_mode(get_canvas_item(),font.is_valid() && font->is_distance_field_hint()); - int font_h = font->get_height(); + int font_h = font->get_height()+line_spacing; int lines_visible = size.y/font_h; int space_w=font->get_char_size(' ').width; int chars_total=0; @@ -372,6 +373,7 @@ void Label::regenerate_word_cache() { int line_width=0; int space_count=0; int space_width=font->get_char_size(' ').width; + int line_spacing = get_constant("line_spacing"); line_count=1; total_char_cache=0; @@ -486,9 +488,9 @@ void Label::regenerate_word_cache() { if (!autowrap) { minsize.width=width; if (max_lines_visible > 0 && line_count > max_lines_visible) { - minsize.height=font->get_height()*max_lines_visible; + minsize.height=(font->get_height()+line_spacing)*max_lines_visible; } else { - minsize.height=font->get_height()*line_count; + minsize.height=(font->get_height()+line_spacing)*line_count; } } diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 21dee62b38..44cc798447 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -41,7 +41,15 @@ void LineEdit::_input_event(InputEvent p_event) { const InputEventMouseButton &b = p_event.mouse_button; - if (b.button_index!=1) + if (b.pressed && b.button_index==BUTTON_RIGHT) { + menu->set_pos(get_global_transform().xform(get_local_mouse_pos())); + menu->set_size(Vector2(1,1)); + menu->popup(); + grab_focus(); + return; + } + + if (b.button_index!=BUTTON_LEFT) break; if (b.pressed) { @@ -143,24 +151,10 @@ void LineEdit::_input_event(InputEvent p_event) { if( k.mod.command && editable) { - int old_cursor_pos = cursor_pos; - text = undo_text; - - Ref<Font> font = get_font("font"); - - cached_width = 0; - for (int i = 0; i<text.length(); i++) - cached_width += font->get_char_size(text[i]).width; + undo(); - if(old_cursor_pos > text.length()) { - set_cursor_pos(text.length()); - } else { - set_cursor_pos(old_cursor_pos); - } } - emit_signal("text_changed",text); - _change_notify("text"); } break; @@ -460,7 +454,7 @@ void LineEdit::_notification(int p_what) { } break; } - int ofs_max=width-style->get_minimum_size().width; + int ofs_max=width-style->get_minimum_size().width+x_ofs; int char_ofs=window_pos; int y_area=height-style->get_minimum_size().height; @@ -559,6 +553,28 @@ void LineEdit::paste_text() { } +void LineEdit::undo() { + + int old_cursor_pos = cursor_pos; + text = undo_text; + + Ref<Font> font = get_font("font"); + + cached_width = 0; + for (int i = 0; i<text.length(); i++) + cached_width += font->get_char_size(text[i]).width; + + if(old_cursor_pos > text.length()) { + set_cursor_pos(text.length()); + } else { + set_cursor_pos(old_cursor_pos); + } + + emit_signal("text_changed",text); + _change_notify("text"); + +} + void LineEdit::shift_selection_check_pre(bool p_shift) { if (!selection.old_shift && p_shift) { @@ -669,6 +685,8 @@ void LineEdit::set_text(String p_text) { void LineEdit::clear() { clear_internal(); + emit_signal("text_changed",text); + _change_notify("text"); } String LineEdit::get_text() const { @@ -781,8 +799,7 @@ Size2 LineEdit::get_minimum_size() const { Ref<Font> font=get_font("font"); Size2 min=style->get_minimum_size(); - min.height+=font->get_height(); - min.width+=get_constant("minimum_spaces")*font->get_char_size(' ').x; + min+=font->get_string_size(this->text); return min; } @@ -932,6 +949,39 @@ bool LineEdit::is_text_field() const { return true; } +void LineEdit::menu_option(int p_option) { + + switch(p_option) { + case MENU_CUT: { + cut_text(); + } break; + case MENU_COPY: { + + copy_text(); + } break; + case MENU_PASTE: { + + paste_text(); + } break; + case MENU_CLEAR: { + clear(); + } break; + case MENU_SELECT_ALL: { + select_all(); + } break; + case MENU_UNDO: { + + undo(); + } break; + + } + +} + +PopupMenu *LineEdit::get_menu() const { + return menu; +} + void LineEdit::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_align", "align"), &LineEdit::set_align); @@ -952,6 +1002,8 @@ void LineEdit::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_secret","enabled"),&LineEdit::set_secret); ObjectTypeDB::bind_method(_MD("is_secret"),&LineEdit::is_secret); ObjectTypeDB::bind_method(_MD("select","from","to"),&LineEdit::select,DEFVAL(0),DEFVAL(-1)); + ObjectTypeDB::bind_method(_MD("menu_option","option"),&LineEdit::menu_option); + ObjectTypeDB::bind_method(_MD("get_menu:PopupMenu"),&LineEdit::get_menu); ADD_SIGNAL( MethodInfo("text_changed", PropertyInfo( Variant::STRING, "text" )) ); ADD_SIGNAL( MethodInfo("text_entered", PropertyInfo( Variant::STRING, "text" )) ); @@ -961,11 +1013,21 @@ void LineEdit::_bind_methods() { BIND_CONSTANT(ALIGN_RIGHT); BIND_CONSTANT(ALIGN_FILL); - ADD_PROPERTY( PropertyInfo( Variant::STRING, "text" ), _SCS("set_text"),_SCS("get_text") ); + BIND_CONSTANT( MENU_CUT ); + BIND_CONSTANT( MENU_COPY ); + BIND_CONSTANT( MENU_PASTE ); + BIND_CONSTANT( MENU_CLEAR ); + BIND_CONSTANT( MENU_SELECT_ALL ); + BIND_CONSTANT( MENU_UNDO ); + BIND_CONSTANT( MENU_MAX ); + + ADD_PROPERTYNZ( PropertyInfo( Variant::STRING, "text" ), _SCS("set_text"),_SCS("get_text") ); ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), _SCS("set_align"), _SCS("get_align")); - ADD_PROPERTY( PropertyInfo( Variant::INT, "max_length" ), _SCS("set_max_length"),_SCS("get_max_length") ); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "editable" ), _SCS("set_editable"),_SCS("is_editable") ); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "secret" ), _SCS("set_secret"),_SCS("is_secret") ); + 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_PROPERTY( PropertyInfo( Variant::INT,"focus_mode", PROPERTY_HINT_ENUM, "None,Click,All" ), _SCS("set_focus_mode"), _SCS("get_focus_mode") ); + } LineEdit::LineEdit() { @@ -984,6 +1046,20 @@ LineEdit::LineEdit() { set_stop_mouse(true); + menu = memnew( PopupMenu ); + add_child(menu); + menu->add_item(TTR("Cut"),MENU_CUT,KEY_MASK_CMD|KEY_X); + menu->add_item(TTR("Copy"),MENU_COPY,KEY_MASK_CMD|KEY_C); + menu->add_item(TTR("Paste"),MENU_PASTE,KEY_MASK_CMD|KEY_V); + menu->add_separator(); + menu->add_item(TTR("Select All"),MENU_SELECT_ALL,KEY_MASK_CMD|KEY_A); + menu->add_item(TTR("Clear"),MENU_CLEAR); + menu->add_separator(); + menu->add_item(TTR("Undo"),MENU_UNDO,KEY_MASK_CMD|KEY_Z); + menu->connect("item_pressed",this,"menu_option"); + + + } LineEdit::~LineEdit() { diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 207c6b115b..586a54e950 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -30,6 +30,8 @@ #define LINE_EDIT_H #include "scene/gui/control.h" +#include "scene/gui/popup_menu.h" + /** @author Juan Linietsky <reduzio@gmail.com> */ @@ -45,6 +47,18 @@ public: ALIGN_RIGHT, ALIGN_FILL }; + + enum MenuItems { + MENU_CUT, + MENU_COPY, + MENU_PASTE, + MENU_CLEAR, + MENU_SELECT_ALL, + MENU_UNDO, + MENU_MAX + + }; + private: Align align; @@ -54,6 +68,8 @@ private: String undo_text; String text; + PopupMenu *menu; + int cursor_pos; int window_pos; int max_length; // 0 for no maximum @@ -85,14 +101,12 @@ private: void clear_internal(); void changed_internal(); - void copy_text(); - void cut_text(); - void paste_text(); void _input_event(InputEvent p_event); void _notification(int p_what); + protected: static void _bind_methods(); public: @@ -103,6 +117,8 @@ public: virtual bool can_drop_data(const Point2& p_point,const Variant& p_data) const; virtual void drop_data(const Point2& p_point,const Variant& p_data); + void menu_option(int p_option); + PopupMenu *get_menu() const; void select_all(); @@ -116,6 +132,10 @@ public: void append_at_cursor(String p_text); void clear(); + void copy_text(); + void cut_text(); + void paste_text(); + void undo(); void set_editable(bool p_editable); bool is_editable() const; @@ -127,7 +147,7 @@ public: virtual Size2 get_minimum_size() const; - virtual bool is_text_field() const; + virtual bool is_text_field() const; LineEdit(); ~LineEdit(); diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp index 007d0a709e..065423ae2d 100644 --- a/scene/gui/link_button.cpp +++ b/scene/gui/link_button.cpp @@ -119,6 +119,6 @@ void LinkButton::_bind_methods() { LinkButton::LinkButton() { underline_mode=UNDERLINE_MODE_ALWAYS; - set_focus_mode(FOCUS_NONE); + set_enabled_focus_mode(FOCUS_NONE); set_default_cursor_shape(CURSOR_POINTING_HAND); } diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index 0f415f013d..28d67287d5 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -32,30 +32,15 @@ void MenuButton::_unhandled_key_input(InputEvent p_event) { - //check accelerators - if (p_event.type==InputEvent::KEY && p_event.key.pressed) { + if (p_event.is_pressed() && !p_event.is_echo() && (p_event.type==InputEvent::KEY || p_event.type==InputEvent::ACTION || p_event.type==InputEvent::JOYSTICK_BUTTON)) { if (!get_parent() || !is_visible() || is_disabled()) return; - uint32_t code=p_event.key.scancode; - if (code==0) - code=p_event.key.unicode; - if (p_event.key.mod.control) - code|=KEY_MASK_CTRL; - if (p_event.key.mod.alt) - code|=KEY_MASK_ALT; - if (p_event.key.mod.meta) - code|=KEY_MASK_META; - if (p_event.key.mod.shift) - code|=KEY_MASK_SHIFT; - - - int item = popup->activate_item_by_accelerator(code); + int item = popup->activate_item_by_event(p_event); } - } @@ -123,7 +108,7 @@ MenuButton::MenuButton() { set_flat(true); - set_focus_mode(FOCUS_NONE); + set_enabled_focus_mode(FOCUS_NONE); popup = memnew( PopupMenu ); popup->hide(); add_child(popup); diff --git a/scene/gui/patch_9_frame.cpp b/scene/gui/patch_9_frame.cpp index b6e261714c..3ecee7328b 100644 --- a/scene/gui/patch_9_frame.cpp +++ b/scene/gui/patch_9_frame.cpp @@ -9,10 +9,9 @@ void Patch9Frame::_notification(int p_what) { if (texture.is_null()) return; - Size2 s=get_size(); RID ci = get_canvas_item(); - VS::get_singleton()->canvas_item_add_style_box(ci,Rect2(Point2(),s),texture->get_rid(),Vector2(margin[MARGIN_LEFT],margin[MARGIN_TOP]),Vector2(margin[MARGIN_RIGHT],margin[MARGIN_BOTTOM]),draw_center,modulate); + VS::get_singleton()->canvas_item_add_style_box(ci,Rect2(Point2(),s),region_rect,texture->get_rid(),Vector2(margin[MARGIN_LEFT],margin[MARGIN_TOP]),Vector2(margin[MARGIN_RIGHT],margin[MARGIN_BOTTOM]),draw_center,modulate); // draw_texture_rect(texture,Rect2(Point2(),s),false,modulate); /* @@ -47,12 +46,15 @@ void Patch9Frame::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_modulate"), & Patch9Frame::get_modulate ); ObjectTypeDB::bind_method(_MD("set_patch_margin","margin","value"), & Patch9Frame::set_patch_margin ); ObjectTypeDB::bind_method(_MD("get_patch_margin","margin"), & Patch9Frame::get_patch_margin ); + ObjectTypeDB::bind_method(_MD("set_region_rect","rect"),&Patch9Frame::set_region_rect); + ObjectTypeDB::bind_method(_MD("get_region_rect"),&Patch9Frame::get_region_rect); ObjectTypeDB::bind_method(_MD("set_draw_center","draw_center"), & Patch9Frame::set_draw_center ); ObjectTypeDB::bind_method(_MD("get_draw_center"), & Patch9Frame::get_draw_center ); ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), _SCS("set_texture"),_SCS("get_texture") ); ADD_PROPERTYNO( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate") ); ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "draw_center"), _SCS("set_draw_center"),_SCS("get_draw_center") ); + ADD_PROPERTYNZ( PropertyInfo( Variant::RECT2, "region_rect"), _SCS("set_region_rect"),_SCS("get_region_rect")); ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/left",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_LEFT ); ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/top",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_TOP ); ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/right",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_RIGHT ); @@ -93,6 +95,20 @@ void Patch9Frame::set_patch_margin(Margin p_margin,int p_size) { margin[p_margin]=p_size; update(); minimum_size_changed(); + switch (p_margin) { + case MARGIN_LEFT: + _change_notify("patch_margin/left"); + break; + case MARGIN_TOP: + _change_notify("patch_margin/top"); + break; + case MARGIN_RIGHT: + _change_notify("patch_margin/right"); + break; + case MARGIN_BOTTOM: + _change_notify("patch_margin/bottom"); + break; + } } int Patch9Frame::get_patch_margin(Margin p_margin) const{ @@ -101,6 +117,22 @@ int Patch9Frame::get_patch_margin(Margin p_margin) const{ return margin[p_margin]; } +void Patch9Frame::set_region_rect(const Rect2& p_region_rect) { + + if (region_rect==p_region_rect) + return; + + region_rect=p_region_rect; + + item_rect_changed(); + _change_notify("region_rect"); +} + +Rect2 Patch9Frame::get_region_rect() const { + + return region_rect; +} + void Patch9Frame::set_draw_center(bool p_draw) { draw_center=p_draw; @@ -128,5 +160,3 @@ Patch9Frame::Patch9Frame() { Patch9Frame::~Patch9Frame() { } - - diff --git a/scene/gui/patch_9_frame.h b/scene/gui/patch_9_frame.h index 562a5b1d77..52e2324c3d 100644 --- a/scene/gui/patch_9_frame.h +++ b/scene/gui/patch_9_frame.h @@ -11,6 +11,7 @@ class Patch9Frame : public Control { bool draw_center; int margin[4]; + Rect2 region_rect; Color modulate; Ref<Texture> texture; protected: @@ -30,6 +31,9 @@ public: void set_patch_margin(Margin p_margin,int p_size); int get_patch_margin(Margin p_margin) const; + void set_region_rect(const Rect2& p_region_rect); + Rect2 get_region_rect() const; + void set_draw_center(bool p_enable); bool get_draw_center() const; diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index 0d9a76937c..8d02d0e4e5 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -44,6 +44,8 @@ void Popup::_notification(int p_what) { notification(NOTIFICATION_POPUP_HIDE); emit_signal("popup_hide"); } + + update_configuration_warning(); } if (p_what==NOTIFICATION_ENTER_TREE) { @@ -282,6 +284,14 @@ Popup::Popup() { hide(); } +String Popup::get_configuration_warning() const { + + if (is_visible()) { + return TTR("Popups will hide by default unless you call popup() or any of the popup*() functions. Making them visible for editing is fine though, but they will hide upon running."); + } + + return String(); +} Popup::~Popup() { diff --git a/scene/gui/popup.h b/scene/gui/popup.h index 8afcdc01db..dccaf2ae69 100644 --- a/scene/gui/popup.h +++ b/scene/gui/popup.h @@ -65,6 +65,7 @@ public: void set_as_minsize(); virtual void popup(); + virtual String get_configuration_warning() const; Popup(); ~Popup(); diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 819885809b..b3f18bf8fa 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -32,9 +32,16 @@ #include "translation.h" #include "os/input.h" -String PopupMenu::_get_accel_text(uint32_t p_accel) const { +String PopupMenu::_get_accel_text(int p_item) const { + + ERR_FAIL_INDEX_V(p_item,items.size(),String()); + + if (items[p_item].shortcut.is_valid()) + return items[p_item].shortcut->get_as_text(); + else if (items[p_item].accel) + return keycode_get_string(items[p_item].accel); + return String(); - return keycode_get_string(p_accel); /* String atxt; if (p_accel&KEY_MASK_SHIFT) @@ -87,14 +94,15 @@ Size2 PopupMenu::get_minimum_size() const { size.width+=check_w+hseparation; } - size.width+=font->get_string_size(items[i].text).width; + String text = items[i].shortcut.is_valid() ? String(tr(items[i].shortcut->get_name())) : items[i].text; + size.width+=font->get_string_size(text).width; if (i>0) size.height+=vseparation; - if (items[i].accel) { + if (items[i].accel || (items[i].shortcut.is_valid() && items[i].shortcut->is_valid())) { int accel_w = hseparation*2; - accel_w+=font->get_string_size(_get_accel_text(items[i].accel)).width; + accel_w+=font->get_string_size(_get_accel_text(i)).width; accel_max_w = MAX( accel_w, accel_max_w ); } @@ -484,13 +492,15 @@ void PopupMenu::_notification(int p_what) { } item_ofs.y+=font->get_ascent(); - if (!items[i].separator) - font->draw(ci,item_ofs+Point2(0,Math::floor((h-font_h)/2.0)),items[i].text,items[i].disabled?font_color_disabled:(i==mouse_over?font_color_hover:font_color)); + String text = items[i].shortcut.is_valid() ? String(tr(items[i].shortcut->get_name())) : items[i].text; + if (!items[i].separator) { + font->draw(ci,item_ofs+Point2(0,Math::floor((h-font_h)/2.0)),text,items[i].disabled?font_color_disabled:(i==mouse_over?font_color_hover:font_color)); + } - if (items[i].accel) { + if (items[i].accel || (items[i].shortcut.is_valid() && items[i].shortcut->is_valid())) { //accelerator - String text = _get_accel_text(items[i].accel); + String text = _get_accel_text(i); item_ofs.x=size.width-style->get_margin(MARGIN_RIGHT)-font->get_string_size(text).width; font->draw(ci,item_ofs+Point2(0,Math::floor((h-font_h)/2.0)),text,i==mouse_over?font_color_hover:font_color_accel); @@ -570,6 +580,64 @@ void PopupMenu::add_check_item(const String& p_label,int p_ID,uint32_t p_accel) update(); } + +void PopupMenu::add_icon_shortcut(const Ref<Texture>& p_icon,const Ref<ShortCut>& p_shortcut,int p_ID) { + + ERR_FAIL_COND(p_shortcut.is_null()); + + _ref_shortcut(p_shortcut); + + Item item; + item.ID=p_ID; + item.icon=p_icon; + item.shortcut=p_shortcut; + items.push_back(item); + update(); + +} + +void PopupMenu::add_shortcut(const Ref<ShortCut>& p_shortcut,int p_ID){ + + ERR_FAIL_COND(p_shortcut.is_null()); + + _ref_shortcut(p_shortcut); + + Item item; + item.ID=p_ID; + item.shortcut=p_shortcut; + items.push_back(item); + update(); + +} +void PopupMenu::add_icon_check_shortcut(const Ref<Texture>& p_icon,const Ref<ShortCut>& p_shortcut,int p_ID){ + + ERR_FAIL_COND(p_shortcut.is_null()); + + _ref_shortcut(p_shortcut); + + Item item; + item.ID=p_ID; + item.shortcut=p_shortcut; + item.checkable=true; + item.icon=p_icon; + items.push_back(item); + update(); +} + +void PopupMenu::add_check_shortcut(const Ref<ShortCut>& p_shortcut,int p_ID){ + + ERR_FAIL_COND(p_shortcut.is_null()); + + _ref_shortcut(p_shortcut); + + Item item; + item.ID=p_ID; + item.shortcut=p_shortcut; + item.checkable=true; + items.push_back(item); + update(); +} + void PopupMenu::set_item_text(int p_idx,const String& p_text) { ERR_FAIL_INDEX(p_idx,items.size()); @@ -701,6 +769,12 @@ String PopupMenu::get_item_tooltip(int p_idx) const { return items[p_idx].tooltip; } +Ref<ShortCut> PopupMenu::get_item_shortcut(int p_idx) const { + + ERR_FAIL_INDEX_V(p_idx,items.size(),Ref<ShortCut>()); + return items[p_idx].shortcut; +} + void PopupMenu::set_item_as_separator(int p_idx, bool p_separator) { ERR_FAIL_INDEX(p_idx,items.size()); @@ -730,6 +804,21 @@ void PopupMenu::set_item_tooltip(int p_idx,const String& p_tooltip) { update(); } +void PopupMenu::set_item_shortcut(int p_idx, const Ref<ShortCut>& p_shortcut) { + ERR_FAIL_INDEX(p_idx,items.size()); + if (items[p_idx].shortcut.is_valid()) { + _unref_shortcut(items[p_idx].shortcut); + } + items[p_idx].shortcut=p_shortcut; + + if (items[p_idx].shortcut.is_valid()) { + _ref_shortcut(items[p_idx].shortcut); + } + + + update(); +} + bool PopupMenu::is_item_checkable(int p_idx) const { ERR_FAIL_INDEX_V(p_idx,items.size(),false); return items[p_idx].checkable; @@ -740,14 +829,36 @@ int PopupMenu::get_item_count() const { return items.size(); } -bool PopupMenu::activate_item_by_accelerator(uint32_t p_accel) { +bool PopupMenu::activate_item_by_event(const InputEvent& p_event) { + + uint32_t code=0; + if (p_event.type==InputEvent::KEY) { + code=p_event.key.scancode; + if (code==0) + code=p_event.key.unicode; + if (p_event.key.mod.control) + code|=KEY_MASK_CTRL; + if (p_event.key.mod.alt) + code|=KEY_MASK_ALT; + if (p_event.key.mod.meta) + code|=KEY_MASK_META; + if (p_event.key.mod.shift) + code|=KEY_MASK_SHIFT; + } + int il=items.size(); for(int i=0;i<il;i++) { if (is_item_disabled(i)) continue; - if (items[i].accel==p_accel) { + + if (items[i].shortcut.is_valid() && items[i].shortcut->is_shortcut(p_event)) { + activate_item(i); + return true; + } + + if (code!=0 && items[i].accel==code) { activate_item(i); return true; } @@ -761,7 +872,7 @@ bool PopupMenu::activate_item_by_accelerator(uint32_t p_accel) { if(!pm) continue; - if(pm->activate_item_by_accelerator(p_accel)) { + if(pm->activate_item_by_event(p_event)) { return true; } } @@ -791,6 +902,12 @@ void PopupMenu::activate_item(int p_item) { void PopupMenu::remove_item(int p_idx) { + ERR_FAIL_INDEX(p_idx,items.size()); + + if (items[p_idx].shortcut.is_valid()) { + _unref_shortcut(items[p_idx].shortcut); + } + items.remove(p_idx); update(); } @@ -806,6 +923,11 @@ void PopupMenu::add_separator() { void PopupMenu::clear() { + for(int i=0;i<items.size();i++) { + if (items[i].shortcut.is_valid()) { + _unref_shortcut(items[i].shortcut); + } + } items.clear(); mouse_over=-1; update(); @@ -834,6 +956,27 @@ Array PopupMenu::_get_items() const { return items; } + +void PopupMenu::_ref_shortcut( Ref<ShortCut> p_sc) { + + if (!shortcut_refcount.has(p_sc)) { + shortcut_refcount[p_sc]=1; + p_sc->connect("changed",this,"update"); + } else { + shortcut_refcount[p_sc]+=1; + } +} + +void PopupMenu::_unref_shortcut(Ref<ShortCut> p_sc) { + + ERR_FAIL_COND(!shortcut_refcount.has(p_sc)); + shortcut_refcount[p_sc]--; + if (shortcut_refcount[p_sc]==0) { + p_sc->disconnect("changed",this,"update"); + shortcut_refcount.erase(p_sc); + } +} + void PopupMenu::_set_items(const Array& p_items){ ERR_FAIL_COND(p_items.size() % 10); @@ -912,12 +1055,20 @@ void PopupMenu::_bind_methods() { ObjectTypeDB::bind_method(_MD("add_icon_check_item","texture","label","id","accel"),&PopupMenu::add_icon_check_item,DEFVAL(-1),DEFVAL(0)); ObjectTypeDB::bind_method(_MD("add_check_item","label","id","accel"),&PopupMenu::add_check_item,DEFVAL(-1),DEFVAL(0)); ObjectTypeDB::bind_method(_MD("add_submenu_item","label","submenu","id"),&PopupMenu::add_submenu_item,DEFVAL(-1)); + + ObjectTypeDB::bind_method(_MD("add_icon_shortcut","texture","shortcut:ShortCut","id"),&PopupMenu::add_icon_shortcut,DEFVAL(-1)); + ObjectTypeDB::bind_method(_MD("add_shortcut","shortcut:ShortCut","id"),&PopupMenu::add_shortcut,DEFVAL(-1)); + ObjectTypeDB::bind_method(_MD("add_icon_check_shortcut","texture","shortcut:ShortCut","id"),&PopupMenu::add_icon_check_shortcut,DEFVAL(-1)); + ObjectTypeDB::bind_method(_MD("add_check_shortcut","shortcut:ShortCut","id"),&PopupMenu::add_check_shortcut,DEFVAL(-1)); + + ObjectTypeDB::bind_method(_MD("set_item_text","idx","text"),&PopupMenu::set_item_text); ObjectTypeDB::bind_method(_MD("set_item_icon","idx","icon"),&PopupMenu::set_item_icon); ObjectTypeDB::bind_method(_MD("set_item_accelerator","idx","accel"),&PopupMenu::set_item_accelerator); ObjectTypeDB::bind_method(_MD("set_item_metadata","idx","metadata"),&PopupMenu::set_item_metadata); ObjectTypeDB::bind_method(_MD("set_item_checked","idx","checked"),&PopupMenu::set_item_checked); ObjectTypeDB::bind_method(_MD("set_item_disabled","idx","disabled"),&PopupMenu::set_item_disabled); + ObjectTypeDB::bind_method(_MD("set_item_shortcut","idx","shortcut:ShortCut"),&PopupMenu::set_item_shortcut); ObjectTypeDB::bind_method(_MD("set_item_submenu","idx","submenu"),&PopupMenu::set_item_submenu); ObjectTypeDB::bind_method(_MD("set_item_as_separator","idx","enable"),&PopupMenu::set_item_as_separator); ObjectTypeDB::bind_method(_MD("set_item_as_checkable","idx","enable"),&PopupMenu::set_item_as_checkable); @@ -926,6 +1077,7 @@ void PopupMenu::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_item_icon","idx"),&PopupMenu::get_item_icon); ObjectTypeDB::bind_method(_MD("get_item_metadata","idx"),&PopupMenu::get_item_metadata); ObjectTypeDB::bind_method(_MD("get_item_accelerator","idx"),&PopupMenu::get_item_accelerator); + ObjectTypeDB::bind_method(_MD("get_item_shortcut:ShortCut","idx"),&PopupMenu::get_item_shortcut); ObjectTypeDB::bind_method(_MD("get_item_submenu","idx"),&PopupMenu::get_item_submenu); ObjectTypeDB::bind_method(_MD("is_item_separator","idx"),&PopupMenu::is_item_separator); ObjectTypeDB::bind_method(_MD("is_item_checkable","idx"),&PopupMenu::is_item_checkable); diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index 0e98765dc4..f35e91d4e4 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -34,6 +34,9 @@ /** @author Juan Linietsky <reduzio@gmail.com> */ + + + class PopupMenu : public Popup { OBJ_TYPE(PopupMenu, Popup ); @@ -51,6 +54,7 @@ class PopupMenu : public Popup { String tooltip; uint32_t accel; int _ofs_cache; + Ref<ShortCut> shortcut; Item() { checked=false; checkable=false; separator=false; accel=0; disabled=false; _ofs_cache=0; } }; @@ -62,7 +66,7 @@ class PopupMenu : public Popup { int mouse_over; int submenu_over; Rect2 parent_rect; - String _get_accel_text(uint32_t p_accel) const; + String _get_accel_text(int p_item) const; int _get_mouse_over(const Point2& p_over) const; virtual Size2 get_minimum_size() const; void _input_event(const InputEvent &p_event); @@ -75,6 +79,10 @@ class PopupMenu : public Popup { Array _get_items() const; void _set_items(const Array& p_items); + Map< Ref<ShortCut>, int> shortcut_refcount; + + void _ref_shortcut(Ref<ShortCut> p_sc); + void _unref_shortcut( Ref<ShortCut> p_sc); protected: virtual bool has_point(const Point2& p_point) const; @@ -90,6 +98,11 @@ public: void add_check_item(const String& p_label,int p_ID=-1,uint32_t p_accel=0); void add_submenu_item(const String& p_label,const String& p_submenu, int p_ID=-1); + void add_icon_shortcut(const Ref<Texture>& p_icon,const Ref<ShortCut>& p_shortcut,int p_ID=-1); + void add_shortcut(const Ref<ShortCut>& p_shortcut,int p_ID=-1); + void add_icon_check_shortcut(const Ref<Texture>& p_icon,const Ref<ShortCut>& p_shortcut,int p_ID=-1); + void add_check_shortcut(const Ref<ShortCut>& p_shortcut,int p_ID=-1); + void set_item_text(int p_idx,const String& p_text); void set_item_icon(int p_idx,const Ref<Texture>& p_icon); void set_item_checked(int p_idx,bool p_checked); @@ -101,6 +114,7 @@ public: void set_item_as_separator(int p_idx, bool p_separator); void set_item_as_checkable(int p_idx, bool p_checkable); void set_item_tooltip(int p_idx,const String& p_tooltip); + void set_item_shortcut(int p_idx, const Ref<ShortCut>& p_shortcut); String get_item_text(int p_idx) const; Ref<Texture> get_item_icon(int p_idx) const; @@ -114,10 +128,11 @@ public: bool is_item_separator(int p_idx) const; bool is_item_checkable(int p_idx) const; String get_item_tooltip(int p_idx) const; + Ref<ShortCut> get_item_shortcut(int p_idx) const; int get_item_count() const; - bool activate_item_by_accelerator(uint32_t p_accel); + bool activate_item_by_event(const InputEvent& p_event); void activate_item(int p_item); void remove_item(int p_idx); diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp index f66f909517..d5d14ad649 100644 --- a/scene/gui/slider.cpp +++ b/scene/gui/slider.cpp @@ -237,6 +237,7 @@ void Slider::_bind_methods() { ADD_PROPERTY( PropertyInfo( Variant::INT, "tick_count", PROPERTY_HINT_RANGE,"0,4096,1"), _SCS("set_ticks"), _SCS("get_ticks") ); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "ticks_on_borders" ), _SCS("set_ticks_on_borders"), _SCS("get_ticks_on_borders") ); + ADD_PROPERTY( PropertyInfo( Variant::INT,"focus_mode", PROPERTY_HINT_ENUM, "None,Click,All" ), _SCS("set_focus_mode"), _SCS("get_focus_mode") ); } diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 1c6a97bab8..d19e5f0d60 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -411,6 +411,10 @@ void TabContainer::_notification(int p_what) { panel->draw(ci, Rect2( 0, top_size.height, size.width, size.height-top_size.height)); } break; + case NOTIFICATION_THEME_CHANGED: { + + call_deferred("set_current_tab",get_current_tab()); //wait until all changed theme + } break; } } diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 8df0c6d254..fe03b34105 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -56,6 +56,10 @@ static bool _is_number(CharType c) { return (c >= '0' && c <= '9'); } +static bool _is_hex_symbol(CharType c) { + return ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); +} + static bool _is_pair_right_symbol(CharType c) { return c == '"' || @@ -310,6 +314,10 @@ void TextEdit::_update_scrollbars() { if (line_numbers) total_width += cache.line_number_w; + if (draw_breakpoint_gutter) { + total_width += cache.breakpoint_gutter_width; + } + bool use_hscroll=true; bool use_vscroll=true; @@ -408,9 +416,15 @@ void TextEdit::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { _update_caches(); - }; + } break; case NOTIFICATION_DRAW: { + if (draw_breakpoint_gutter) { + cache.breakpoint_gutter_width = breakpoint_gutter_width; + } else { + cache.breakpoint_gutter_width = 0; + } + int line_number_char_count=0; { @@ -435,7 +449,7 @@ void TextEdit::_notification(int p_what) { RID ci = get_canvas_item(); - int xmargin_beg=cache.style_normal->get_margin(MARGIN_LEFT)+cache.line_number_w; + int xmargin_beg=cache.style_normal->get_margin(MARGIN_LEFT)+cache.line_number_w+cache.breakpoint_gutter_width; int xmargin_end=cache.size.width-cache.style_normal->get_margin(MARGIN_RIGHT); //let's do it easy for now: cache.style_normal->draw(ci,Rect2(Point2(),cache.size)); @@ -673,22 +687,18 @@ void TextEdit::_notification(int p_what) { bool in_word = false; bool in_function_name = false; bool in_member_variable = false; + bool is_hex_notation = false; Color keyword_color; // check if line contains highlighted word int highlighted_text_col = -1; - if (highlighted_text.length() != 0) { - highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, 0); - } + int search_text_col = -1; - if (cache.line_number_w) { - String fc = String::num(line+1); - while (fc.length() < line_number_char_count) { - fc="0"+fc; - } + if (!search_text.empty()) + search_text_col = _get_column_pos_of_word(search_text, str, search_flags, 0); - cache.font->draw(ci,Point2(cache.style_normal->get_margin(MARGIN_LEFT),ofs_y+cache.font->get_ascent()),fc,cache.line_number_color); - } + if (highlighted_text.length() != 0 && highlighted_text != search_text) + highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, SEARCH_MATCH_CASE|SEARCH_WHOLE_WORDS, 0); const Map<int,Text::ColorRegionInfo>& cri_map=text.get_color_region_info(line); @@ -703,11 +713,28 @@ void TextEdit::_notification(int p_what) { VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(xmargin_beg, ofs_y,xmargin_end-xmargin_beg,get_row_height()),cache.breakpoint_color); } - if (line==cursor.line) { + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(0, ofs_y,xmargin_end,get_row_height()),cache.current_line_color); + } + + // draw breakpoint marker + if (text.is_breakpoint(line)) { + if (draw_breakpoint_gutter) { + int vertical_gap = cache.breakpoint_gutter_width / 2; + int marker_size = cache.breakpoint_gutter_width - vertical_gap; + // no transparency on marker + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cache.style_normal->get_margin(MARGIN_LEFT) + 1, ofs_y + vertical_gap ,marker_size, marker_size),Color(cache.breakpoint_color.r, cache.breakpoint_color.g, cache.breakpoint_color.b)); + } + } + - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(xmargin_beg, ofs_y,xmargin_end-xmargin_beg,get_row_height()),cache.current_line_color); + if (cache.line_number_w) { + String fc = String::num(line+1); + while (fc.length() < line_number_char_count) { + fc="0"+fc; + } + cache.font->draw(ci,Point2(cache.style_normal->get_margin(MARGIN_LEFT)+cache.breakpoint_gutter_width,ofs_y+cache.font->get_ascent()),fc,cache.line_number_color); } for (int j=0;j<str.length();j++) { @@ -731,20 +758,31 @@ void TextEdit::_notification(int p_what) { in_region=-1; //reset regions that end at end of line } + // allow ABCDEF in hex notation + if (is_hex_notation && (_is_hex_symbol(str[j]) || is_number)) { + is_number = true; + } else { + is_hex_notation = false; + } + + // check for dot or 'x' for hex notation in floating point number + if ((str[j] == '.' || str[j] == 'x') && !in_word && prev_is_number && !is_number) { + is_number = true; + is_symbol = false; + + if (str[j] == 'x' && str[j-1] == '0') { + is_hex_notation = true; + } + } + if (!in_word && _is_char(str[j])) { in_word = true; } - if (in_keyword || in_word) { + if ((in_keyword || in_word) && !is_hex_notation) { is_number = false; } - // check for dot in floating point number - if (str[j] == '.' && !in_word && prev_is_number) { - is_number = true; - is_symbol = false; - } - if (is_symbol && str[j] != '.' && in_word) { in_word = false; } @@ -863,20 +901,45 @@ void TextEdit::_notification(int p_what) { break; } - bool in_selection = (selection.active && line>=selection.from_line && line<=selection.to_line && (line>selection.from_line || j>=selection.from_column) && (line<selection.to_line || j<selection.to_column)); + bool in_search_result=false; + + if (search_text_col != -1) { + // if we are at the end check for new search result on same line + if (j >= search_text_col+search_text.length()) + search_text_col = _get_column_pos_of_word(search_text, str, search_flags, j); + in_search_result = j >= search_text_col && j < search_text_col+search_text.length(); + + if (in_search_result) { + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin, ofs_y ), Size2i(char_w, get_row_height())),cache.search_result_color); + } + } + + bool in_selection = (selection.active && line>=selection.from_line && line<=selection.to_line && (line>selection.from_line || j>=selection.from_column) && (line<selection.to_line || j<selection.to_column)); if (in_selection) { //inside selection! VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin, ofs_y ), Size2i(char_w,get_row_height())),cache.selection_color); } + if (in_search_result) { + Color border_color=(line==search_result_line && j>=search_result_col && j<search_result_col+search_text.length())?cache.font_color:cache.search_result_border_color; + + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin, ofs_y ), Size2i(char_w,1)),border_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin, ofs_y+get_row_height()-1 ), Size2i(char_w,1)),border_color); + + if (j==search_text_col) + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin, ofs_y ), Size2i(1,get_row_height())),border_color); + if (j==search_text_col+search_text.length()-1) + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin+char_w-1, ofs_y ), Size2i(1,get_row_height())),border_color); + } + if (highlight_all_occurrences) { if (highlighted_text_col != -1) { // if we are at the end check for new word on same line if (j > highlighted_text_col+highlighted_text.length()) { - highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, j); + highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, SEARCH_MATCH_CASE|SEARCH_WHOLE_WORDS, j); } bool in_highlighted_word = (j >= highlighted_text_col && j < highlighted_text_col+highlighted_text.length()); @@ -1331,7 +1394,7 @@ void TextEdit::_get_mouse_pos(const Point2i& p_mouse, int &r_row, int &r_col) co col=text[row].size(); } else { - col=p_mouse.x-(cache.style_normal->get_margin(MARGIN_LEFT)+cache.line_number_w); + col=p_mouse.x-(cache.style_normal->get_margin(MARGIN_LEFT)+cache.line_number_w+cache.breakpoint_gutter_width); col+=cursor.x_ofs; col=get_char_pos_for( col, get_line(row) ); } @@ -1405,6 +1468,15 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { int row,col; _get_mouse_pos(Point2i(mb.x,mb.y), row,col); + // toggle breakpoint on gutter click + if (draw_breakpoint_gutter) { + 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)); + return; + } + } + int prev_col=cursor.column; int prev_line=cursor.line; @@ -1518,6 +1590,15 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { update(); } + + if (mb.button_index==BUTTON_RIGHT) { + + menu->set_pos(get_global_transform().xform(get_local_mouse_pos())); + menu->set_size(Vector2(1,1)); + menu->popup(); + grab_focus(); + + } } else { if (mb.button_index==BUTTON_LEFT) @@ -1795,7 +1876,9 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } if (clear) { - begin_complex_operation(); + if (!dobreak) { + begin_complex_operation(); + } selection.active=false; update(); _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); @@ -1867,7 +1950,8 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { if (completion_hint!="") { completion_hint=""; update(); - + } else { + scancode_handled=false; } } break; case KEY_TAB: { @@ -2821,7 +2905,7 @@ void TextEdit::adjust_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; + 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 @@ -3050,7 +3134,8 @@ void TextEdit::insert_text_at_cursor(const String& p_text) { } Control::CursorShape TextEdit::get_cursor_shape(const Point2& p_pos) const { - if(completion_active && completion_rect.has_point(p_pos)) { + int gutter=cache.style_normal->get_margin(MARGIN_LEFT)+cache.line_number_w+cache.breakpoint_gutter_width; + if((completion_active && completion_rect.has_point(p_pos)) || p_pos.x < gutter) { return CURSOR_ARROW; } return CURSOR_IBEAM; @@ -3195,6 +3280,8 @@ void TextEdit::_update_caches() { cache.breakpoint_color=get_color("breakpoint_color"); cache.brace_mismatch_color=get_color("brace_mismatch_color"); cache.word_highlighted_color=get_color("word_highlighted_color"); + cache.search_result_color=get_color("search_result_color"); + cache.search_result_border_color=get_color("search_result_border_color"); cache.line_spacing=get_constant("line_spacing"); cache.row_height = cache.font->get_height() + cache.line_spacing; cache.tab_icon=get_icon("tab"); @@ -3456,12 +3543,26 @@ String TextEdit::get_word_under_cursor() const { return text[cursor.line].substr(prev_cc, next_cc-prev_cc); } +void TextEdit::set_search_text(const String &p_search_text) { + search_text = p_search_text; +} + +void TextEdit::set_search_flags(uint32_t p_flags) { + search_flags = p_flags; +} + +void TextEdit::set_current_search_result(int line, int col) { + search_result_line = line; + search_result_col = col; + update(); +} + void TextEdit::set_highlight_all_occurrences(const bool p_enabled) { highlight_all_occurrences = p_enabled; update(); } -int TextEdit::_get_column_pos_of_word(const String &p_key, const String &p_search, int p_from_column) { +int TextEdit::_get_column_pos_of_word(const String &p_key, const String &p_search, uint32_t p_search_flags, int p_from_column) { int col = -1; if (p_key.length() > 0 && p_search.length() > 0) { @@ -3469,12 +3570,15 @@ int TextEdit::_get_column_pos_of_word(const String &p_key, const String &p_searc p_from_column = 0; } - while (col == -1 && p_from_column <= p_search.length()) { - // match case - col = p_search.findn(p_key, p_from_column); + while (col == -1 && p_from_column <= p_search.length()) { + if (p_search_flags&SEARCH_MATCH_CASE) { + col = p_search.find(p_key,p_from_column); + } else { + col = p_search.findn(p_key,p_from_column); + } // whole words only - if (col != -1) { + if (col != -1 && p_search_flags&SEARCH_WHOLE_WORDS) { p_from_column=col; if (col > 0 && _is_text_char(p_search[col-1])) { @@ -3540,10 +3644,8 @@ bool TextEdit::search(const String &p_key,uint32_t p_search_flags, int p_from_li //wrapped if (p_search_flags&SEARCH_BACKWARDS) { - text_line=text_line.substr(from_column,text_line.length()); from_column=text_line.length(); } else { - text_line=text_line.substr(0,from_column); from_column=0; } @@ -3554,7 +3656,6 @@ bool TextEdit::search(const String &p_key,uint32_t p_search_flags, int p_from_li } else { - //text_line=text_line.substr(0,p_from_column); //wrap around for missing begining. if (p_search_flags&SEARCH_BACKWARDS) from_column=text_line.length()-1; else @@ -3563,12 +3664,25 @@ bool TextEdit::search(const String &p_key,uint32_t p_search_flags, int p_from_li pos=-1; - if (!(p_search_flags&SEARCH_BACKWARDS)) { + int pos_from=0; + int last_pos=-1; + while ((last_pos=(p_search_flags&SEARCH_MATCH_CASE)?text_line.find(p_key,pos_from):text_line.findn(p_key,pos_from))!=-1) { - pos = (p_search_flags&SEARCH_MATCH_CASE)?text_line.find(p_key,from_column):text_line.findn(p_key,from_column); - } else { + if (p_search_flags&SEARCH_BACKWARDS) { + + if (last_pos>from_column) + break; + pos=last_pos; + + } else { - pos = (p_search_flags&SEARCH_MATCH_CASE)?text_line.rfind(p_key,from_column):text_line.rfindn(p_key,from_column); + if (last_pos>=from_column) { + pos=last_pos; + break; + } + } + + pos_from=last_pos+p_key.length(); } if (pos!=-1 && (p_search_flags&SEARCH_WHOLE_WORDS)) { @@ -4142,10 +4256,60 @@ void TextEdit::set_show_line_numbers(bool p_show) { update(); } +void TextEdit::set_draw_breakpoint_gutter(bool p_draw) { + draw_breakpoint_gutter = p_draw; + update(); +} + +bool TextEdit::is_drawing_breakpoint_gutter() const { + return draw_breakpoint_gutter; +} + +void TextEdit::set_breakpoint_gutter_width(int p_gutter_width) { + breakpoint_gutter_width = p_gutter_width; + update(); +} + +int TextEdit::get_breakpoint_gutter_width() const { + return cache.breakpoint_gutter_width; +} + bool TextEdit::is_text_field() const { return true; } + +void TextEdit::menu_option(int p_option) { + + switch( p_option ) { + case MENU_CUT: { + + cut(); + } break; + case MENU_COPY: { + copy(); + } break; + case MENU_PASTE: { + + paste(); + } break; + case MENU_CLEAR: { + clear(); + } break; + case MENU_SELECT_ALL: { + select_all(); + } break; + case MENU_UNDO: { + undo(); + } break; + + }; +} + +PopupMenu *TextEdit::get_menu() const { + return menu; +} + void TextEdit::_bind_methods() { @@ -4215,6 +4379,8 @@ void TextEdit::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_symbol_color","color"),&TextEdit::set_symbol_color); ObjectTypeDB::bind_method(_MD("set_custom_bg_color","color"),&TextEdit::set_custom_bg_color); ObjectTypeDB::bind_method(_MD("clear_colors"),&TextEdit::clear_colors); + ObjectTypeDB::bind_method(_MD("menu_option"),&TextEdit::menu_option); + ObjectTypeDB::bind_method(_MD("get_menu:PopupMenu"),&TextEdit::get_menu); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret/caret_blink"), _SCS("cursor_set_blink_enabled"), _SCS("cursor_get_blink_enabled"));; ADD_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") ); @@ -4223,6 +4389,15 @@ void TextEdit::_bind_methods() { ADD_SIGNAL(MethodInfo("text_changed")); ADD_SIGNAL(MethodInfo("request_completion")); + BIND_CONSTANT( MENU_CUT ); + BIND_CONSTANT( MENU_COPY ); + BIND_CONSTANT( MENU_PASTE ); + BIND_CONSTANT( MENU_CLEAR ); + BIND_CONSTANT( MENU_SELECT_ALL ); + BIND_CONSTANT( MENU_UNDO ); + BIND_CONSTANT( MENU_MAX ); + + } TextEdit::TextEdit() { @@ -4240,6 +4415,8 @@ TextEdit::TextEdit() { cache.row_height=1; cache.line_spacing=1; cache.line_number_w=1; + cache.breakpoint_gutter_width=0; + breakpoint_gutter_width = 0; tab_size=4; text.set_tab_size(tab_size); @@ -4321,12 +4498,27 @@ TextEdit::TextEdit() { completion_line_ofs=0; tooltip_obj=NULL; line_numbers=false; + draw_breakpoint_gutter=false; next_operation_is_complex=false; scroll_past_end_of_file_enabled=false; auto_brace_completion_enabled=false; brace_matching_enabled=false; auto_indent=false; insert_mode = false; + + menu = memnew( PopupMenu ); + add_child(menu); + menu->add_item(TTR("Cut"),MENU_CUT,KEY_MASK_CMD|KEY_X); + menu->add_item(TTR("Copy"),MENU_COPY,KEY_MASK_CMD|KEY_C); + menu->add_item(TTR("Paste"),MENU_PASTE,KEY_MASK_CMD|KEY_V); + menu->add_separator(); + menu->add_item(TTR("Select All"),MENU_SELECT_ALL,KEY_MASK_CMD|KEY_A); + menu->add_item(TTR("Clear"),MENU_CLEAR); + menu->add_separator(); + menu->add_item(TTR("Undo"),MENU_UNDO,KEY_MASK_CMD|KEY_Z); + menu->connect("item_pressed",this,"menu_option"); + + } TextEdit::~TextEdit() diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index ea4f148e91..24a72afd48 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -31,6 +31,7 @@ #include "scene/gui/control.h" #include "scene/gui/scroll_bar.h" +#include "scene/gui/popup_menu.h" #include "scene/main/timer.h" @@ -87,10 +88,13 @@ class TextEdit : public Control { Color current_line_color; Color brace_mismatch_color; Color word_highlighted_color; + Color search_result_color; + Color search_result_border_color; int row_height; int line_spacing; int line_number_w; + int breakpoint_gutter_width; Size2 size; } cache; @@ -221,6 +225,8 @@ class TextEdit : public Control { bool text_changed_dirty; bool undo_enabled; bool line_numbers; + bool draw_breakpoint_gutter; + int breakpoint_gutter_width; bool highlight_all_occurrences; bool scroll_past_end_of_file_enabled; @@ -248,6 +254,11 @@ class TextEdit : public Control { bool callhint_below; Vector2 callhint_offset; + String search_text; + uint32_t search_flags; + int search_result_line; + int search_result_col; + int get_visible_rows() const; int get_char_count(); @@ -286,10 +297,12 @@ class TextEdit : public Control { String _base_get_text(int p_from_line, int p_from_column,int p_to_line,int p_to_column) const; void _base_remove_text(int p_from_line, int p_from_column,int p_to_line,int p_to_column); - int _get_column_pos_of_word(const String &p_key, const String &p_search, int p_from_column); + int _get_column_pos_of_word(const String &p_key, const String &p_search, uint32_t p_search_flags, int p_from_column); DVector<int> _search_bind(const String &p_key,uint32_t p_search_flags, int p_from_line,int p_from_column) const; + PopupMenu *menu; + void _clear(); void _cancel_completion(); void _cancel_code_hint(); @@ -317,6 +330,17 @@ protected: public: + enum MenuItems { + MENU_CUT, + MENU_COPY, + MENU_PASTE, + MENU_CLEAR, + MENU_SELECT_ALL, + MENU_UNDO, + MENU_MAX + + }; + enum SearchFlags { SEARCH_MATCH_CASE=1, @@ -394,6 +418,10 @@ public: void select(int p_from_line,int p_from_column,int p_to_line,int p_to_column); void deselect(); + void set_search_text(const String& p_search_text); + void set_search_flags(uint32_t p_flags); + void set_current_search_result(int line, int col); + void set_highlight_all_occurrences(const bool p_enabled); bool is_selection_active() const; int get_selection_from_line() const; @@ -433,8 +461,16 @@ public: uint32_t get_saved_version() const; void tag_saved_version(); + void menu_option(int p_option); + void set_show_line_numbers(bool p_show); + void set_draw_breakpoint_gutter(bool p_draw); + bool is_drawing_breakpoint_gutter() const; + + void set_breakpoint_gutter_width(int p_gutter_width); + int get_breakpoint_gutter_width() const; + void set_tooltip_request_func(Object *p_obj, const StringName& p_function, const Variant& p_udata); void set_completion(bool p_enabled,const Vector<String>& p_prefixes); @@ -442,6 +478,8 @@ public: void set_code_hint(const String& p_hint); void query_code_comple(); + PopupMenu *get_menu() const; + String get_text_for_completion(); virtual bool is_text_field() const; diff --git a/scene/gui/texture_frame.cpp b/scene/gui/texture_frame.cpp index 73fecf591a..2fe8735fda 100644 --- a/scene/gui/texture_frame.cpp +++ b/scene/gui/texture_frame.cpp @@ -37,9 +37,31 @@ void TextureFrame::_notification(int p_what) { return; - Size2 s=expand?get_size():texture->get_size(); + RID ci = get_canvas_item(); - draw_texture_rect(texture,Rect2(Point2(),s),false,modulate); + + switch(stretch_mode) { + case STRETCH_SCALE_ON_EXPAND: { + Size2 s=expand?get_size():texture->get_size(); + draw_texture_rect(texture,Rect2(Point2(),s),false,modulate); + } break; + case STRETCH_SCALE: { + draw_texture_rect(texture,Rect2(Point2(),get_size()),false,modulate); + } break; + case STRETCH_TILE: { + draw_texture_rect(texture,Rect2(Point2(),get_size()),true,modulate); + } break; + case STRETCH_KEEP: { + draw_texture_rect(texture,Rect2(Point2(),texture->get_size()),false,modulate); + + } break; + case STRETCH_KEEP_CENTERED: { + + Vector2 ofs = (get_size() - texture->get_size())/2; + draw_texture_rect(texture,Rect2(ofs,texture->get_size()),false,modulate); + } break; + } + /* Vector<Point2> points; @@ -76,11 +98,19 @@ void TextureFrame::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_modulate"), & TextureFrame::get_modulate ); ObjectTypeDB::bind_method(_MD("set_expand","enable"), & TextureFrame::set_expand ); ObjectTypeDB::bind_method(_MD("has_expand"), & TextureFrame::has_expand ); + ObjectTypeDB::bind_method(_MD("set_stretch_mode","stretch_mode"), & TextureFrame::set_stretch_mode ); + ObjectTypeDB::bind_method(_MD("get_stretch_mode"), & TextureFrame::get_stretch_mode ); ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), _SCS("set_texture"),_SCS("get_texture") ); ADD_PROPERTYNO( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate") ); ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "expand" ), _SCS("set_expand"),_SCS("has_expand") ); + ADD_PROPERTYNO( PropertyInfo( Variant::INT, "stretch_mode",PROPERTY_HINT_ENUM,"Scale On Expand (Compat),Scale,Tile,Keep,Keep Centered"), _SCS("set_stretch_mode"),_SCS("get_stretch_mode") ); + BIND_CONSTANT( STRETCH_SCALE_ON_EXPAND ); + BIND_CONSTANT( STRETCH_SCALE ); + BIND_CONSTANT( STRETCH_TILE ); + BIND_CONSTANT( STRETCH_KEEP ); + BIND_CONSTANT( STRETCH_KEEP_CENTERED ); } @@ -121,12 +151,24 @@ bool TextureFrame::has_expand() const { return expand; } +void TextureFrame::set_stretch_mode(StretchMode p_mode) { + + stretch_mode=p_mode; + update(); +} + +TextureFrame::StretchMode TextureFrame::get_stretch_mode() const { + + return stretch_mode; +} + TextureFrame::TextureFrame() { expand=false; modulate=Color(1,1,1,1); set_ignore_mouse(true); + stretch_mode=STRETCH_SCALE_ON_EXPAND; } diff --git a/scene/gui/texture_frame.h b/scene/gui/texture_frame.h index e1f0de92df..a4acf588ea 100644 --- a/scene/gui/texture_frame.h +++ b/scene/gui/texture_frame.h @@ -36,10 +36,19 @@ class TextureFrame : public Control { OBJ_TYPE(TextureFrame,Control); - +public: + enum StretchMode { + STRETCH_SCALE_ON_EXPAND, //default, for backwards compatibility + STRETCH_SCALE, + STRETCH_TILE, + STRETCH_KEEP, + STRETCH_KEEP_CENTERED, + }; +private: bool expand; Color modulate; Ref<Texture> texture; + StretchMode stretch_mode; protected: void _notification(int p_what); @@ -57,9 +66,13 @@ public: void set_expand(bool p_expand); bool has_expand() const; + void set_stretch_mode(StretchMode p_mode); + StretchMode get_stretch_mode() const; + TextureFrame(); ~TextureFrame(); }; +VARIANT_ENUM_CAST( TextureFrame::StretchMode ); #endif // TEXTURE_FRAME_H diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp index 89dacc6577..26227d6389 100644 --- a/scene/gui/video_player.cpp +++ b/scene/gui/video_player.cpp @@ -131,7 +131,7 @@ void VideoPlayer::_notification(int p_notification) { if (!playback->is_playing()) return; - double audio_time = OS::get_singleton()->get_ticks_usec()/1000000.0; //AudioServer::get_singleton()->get_mix_time(); + double audio_time = USEC_TO_SEC(OS::get_singleton()->get_ticks_usec()); //AudioServer::get_singleton()->get_mix_time(); double delta = last_audio_time==0?0:audio_time-last_audio_time; last_audio_time=audio_time; |