diff --git a/core/globals.cpp b/core/globals.cpp index 731c5b7dff..d252d4e280 100644 --- a/core/globals.cpp +++ b/core/globals.cpp @@ -1477,7 +1477,6 @@ Globals::Globals() { custom_prop_info["render/mipmap_policy"]=PropertyInfo(Variant::INT,"render/mipmap_policy",PROPERTY_HINT_ENUM,"Allow,Allow For Po2,Disallow"); custom_prop_info["render/thread_model"]=PropertyInfo(Variant::INT,"render/thread_model",PROPERTY_HINT_ENUM,"Single-Unsafe,Single-Safe,Multi-Threaded"); custom_prop_info["physics_2d/thread_model"]=PropertyInfo(Variant::INT,"physics_2d/thread_model",PROPERTY_HINT_ENUM,"Single-Unsafe,Single-Safe,Multi-Threaded"); - set("display/emulate_touchscreen",false); using_datapack=false; } diff --git a/core/object_type_db.cpp b/core/object_type_db.cpp index c291714573..a64b3d2715 100644 --- a/core/object_type_db.cpp +++ b/core/object_type_db.cpp @@ -746,6 +746,25 @@ bool ObjectTypeDB::has_method(StringName p_type,StringName p_method,bool p_no_in } +bool ObjectTypeDB::get_setter_and_type_for_property(const StringName& p_class, const StringName& p_prop, StringName& r_class, StringName& r_setter) { + + TypeInfo *type=types.getptr(p_class); + TypeInfo *check=type; + while(check) { + + if (check->property_setget.has(p_prop)) { + r_class=check->name; + r_setter=check->property_setget[p_prop].setter; + return true; + } + + check=check->inherits_ptr; + } + + return false; + +} + #ifdef DEBUG_METHODS_ENABLED MethodBind* ObjectTypeDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind , const MethodDefinition &method_name, const Variant **p_defs, int p_defcount) { StringName mdname=method_name.name; diff --git a/core/object_type_db.h b/core/object_type_db.h index caa5baddd5..bfa0f921e5 100644 --- a/core/object_type_db.h +++ b/core/object_type_db.h @@ -475,7 +475,9 @@ public: static void get_integer_constant_list(const StringName& p_type, List *p_constants, bool p_no_inheritance=false); static int get_integer_constant(const StringName& p_type, const StringName &p_name, bool *p_success=NULL); static StringName get_category(const StringName& p_node); - + + static bool get_setter_and_type_for_property(const StringName& p_class, const StringName& p_prop, StringName& r_class, StringName& r_setter); + static void set_type_enabled(StringName p_type,bool p_enable); static bool is_type_enabled(StringName p_type); diff --git a/core/os/input.cpp b/core/os/input.cpp index 2b939ede46..cf2938f5cd 100644 --- a/core/os/input.cpp +++ b/core/os/input.cpp @@ -271,6 +271,38 @@ void InputDefault::parse_input_event(const InputEvent& p_event) { mouse_button_mask|=(1<input_event(ev); + } + } break; + case InputEvent::MOUSE_MOTION: { + + if (main_loop && emulate_touch && p_event.mouse_motion.button_mask&1) { + InputEventScreenDrag drag_event; + drag_event.index=0; + drag_event.x=p_event.mouse_motion.x; + drag_event.y=p_event.mouse_motion.y; + drag_event.relative_x=p_event.mouse_motion.relative_x; + drag_event.relative_y=p_event.mouse_motion.relative_y; + drag_event.speed_x=p_event.mouse_motion.speed_x; + drag_event.speed_y=p_event.mouse_motion.speed_y; + + InputEvent ev; + ev.type=InputEvent::SCREEN_DRAG; + ev.screen_drag=drag_event; + + main_loop->input_event(ev); + } + } break; case InputEvent::JOYSTICK_BUTTON: { @@ -362,8 +394,19 @@ void InputDefault::action_release(const StringName& p_action){ } } +void InputDefault::set_emulate_touch(bool p_emulate) { + + emulate_touch=p_emulate; +} + +bool InputDefault::is_emulating_touchscreen() const { + + return emulate_touch; +} + InputDefault::InputDefault() { mouse_button_mask=0; + emulate_touch=false; main_loop=NULL; } diff --git a/core/os/input.h b/core/os/input.h index ce14c2166e..5c69ced825 100644 --- a/core/os/input.h +++ b/core/os/input.h @@ -78,6 +78,8 @@ public: void get_argument_options(const StringName& p_function,int p_idx,List*r_options) const; + virtual bool is_emulating_touchscreen() const=0; + Input(); }; @@ -99,6 +101,8 @@ class InputDefault : public Input { Vector2 mouse_pos; MainLoop *main_loop; + bool emulate_touch; + struct SpeedTrack { uint64_t last_tick; @@ -147,6 +151,9 @@ public: void iteration(float p_step); + void set_emulate_touch(bool p_emulate); + virtual bool is_emulating_touchscreen() const; + InputDefault(); }; diff --git a/core/os/os.cpp b/core/os/os.cpp index efcd492230..2db926e556 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -31,7 +31,7 @@ #include #include "dir_access.h" #include "globals.h" - +#include "input.h" OS* OS::singleton=NULL; @@ -363,7 +363,7 @@ Error OS::set_cwd(const String& p_cwd) { bool OS::has_touchscreen_ui_hint() const { //return false; - return GLOBAL_DEF("display/emulate_touchscreen",false); + return Input::get_singleton() && Input::get_singleton()->is_emulating_touchscreen(); } int OS::get_free_static_memory() const { diff --git a/core/ustring.cpp b/core/ustring.cpp index 3cfc1e4a3c..ff7c8984fa 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -3048,6 +3048,37 @@ bool String::is_valid_identifier() const { //kind of poor should be rewritten properly +String String::world_wrap(int p_chars_per_line) const { + + int from=0; + int last_space=0; + String ret; + for(int i=0;i=p_chars_per_line) { + if (last_space==-1) { + ret+=substr(from,i-from+1)+"\n"; + } else { + ret+=substr(from,last_space-from)+"\n"; + i=last_space; //rewind + } + from=i+1; + last_space=-1; + } else if (operator[](i)==' ' || operator[](i)=='\t') { + last_space=i; + } else if (operator[](i)=='\n') { + ret+=substr(from,i-from); + from=i+1; + last_space=-1; + } + } + + if (fromset_custom_property_info("application/icon",PropertyInfo(Variant::STRING,"application/icon",PROPERTY_HINT_FILE,"*.png,*.webp")); + if (bool(GLOBAL_DEF("display/emulate_touchscreen",false))) { + if (!OS::get_singleton()->has_touchscreen_ui_hint() && Input::get_singleton()) { + //only if no touchscreen ui hint, set emulation + InputDefault *id = Input::get_singleton()->cast_to(); + if (id) + id->set_emulate_touch(true); + } + } MAIN_PRINT("Main: Load Remaps"); path_remap->load_remaps(); diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp index f7aaaf7ee5..283b50f966 100644 --- a/modules/gdscript/gd_parser.cpp +++ b/modules/gdscript/gd_parser.cpp @@ -2625,14 +2625,14 @@ void GDParser::_parse_class(ClassNode *p_class) { Node *subexpr=NULL; - subexpr = _parse_and_reduce_expression(p_class,false); + subexpr = _parse_and_reduce_expression(p_class,false,autoexport); if (!subexpr) return; member.expression=subexpr; if (autoexport) { - if (subexpr->type==Node::TYPE_ARRAY) { + if (1)/*(subexpr->type==Node::TYPE_ARRAY) { member._export.type=Variant::ARRAY; @@ -2640,7 +2640,7 @@ void GDParser::_parse_class(ClassNode *p_class) { member._export.type=Variant::DICTIONARY; - } else { + } else*/ { if (subexpr->type!=Node::TYPE_CONSTANT) { diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index b34d1ba7c8..16632c6627 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -504,6 +504,23 @@ void OS_X11::set_mouse_mode(MouseMode p_mode) { mouse_mode=p_mode; if (mouse_mode==MOUSE_MODE_CAPTURED) { + + while(true) { + //flush pending motion events + + if (XPending(x11_display) > 0) { + XEvent event; + XPeekEvent(x11_display, &event); + if (event.type==MotionNotify) { + XNextEvent(x11_display,&event); + } else { + break; + } + } else { + break; + } + } + if (XGrabPointer(x11_display, x11_window, True, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, GrabModeAsync, GrabModeAsync, @@ -518,6 +535,8 @@ void OS_X11::set_mouse_mode(MouseMode p_mode) { 0,0,0,0, (int)center.x, (int)center.y); input->set_mouse_pos(center); + } else { + do_mouse_warp=false; } } @@ -1131,7 +1150,7 @@ void OS_X11::process_xevents() { //printf("checking events %i\n", XPending(x11_display)); - bool do_mouse_warp=false; + do_mouse_warp=false; while (XPending(x11_display) > 0) { XEvent event; @@ -1244,8 +1263,38 @@ void OS_X11::process_xevents() { } break; case MotionNotify: { - + + // FUCK YOU X11 API YOU SERIOUSLY GROSS ME OUT + // YOU ARE AS GROSS AS LOOKING AT A PUTRID PILE + // OF POOP STICKING OUT OF A CLOGGED TOILET + // HOW THE FUCK I AM SUPPOSED TO KNOW WHICH ONE + // OF THE MOTION NOTIFY EVENTS IS THE ONE GENERATED + // BY WARPING THE MOUSE POINTER? + // YOU ARE FORCING ME TO FILTER ONE BY ONE TO FIND IT + // PLEASE DO ME A FAVOR AND DIE DROWNED IN A FECAL + // MOUNTAIN BECAUSE THAT'S WHERE YOU BELONG. + + while(true) { + if (mouse_mode==MOUSE_MODE_CAPTURED && event.xmotion.x==current_videomode.width/2 && event.xmotion.y==current_videomode.height/2) { + //this is likely the warp event since it was warped here + center=Vector2(event.xmotion.x,event.xmotion.y); + break; + } + + if (XPending(x11_display) > 0) { + XEvent tevent; + XPeekEvent(x11_display, &tevent); + if (tevent.type==MotionNotify) { + XNextEvent(x11_display,&event); + } else { + break; + } + } else { + break; + } + } + last_timestamp=event.xmotion.time; // Motion is also simple. diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index 261a54dd25..12f0aec611 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -114,6 +114,7 @@ class OS_X11 : public OS_Unix { bool minimized; int dpad_last[2]; + bool do_mouse_warp; const char *cursor_theme; int cursor_size; diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp index c521952f9b..6705cebf37 100644 --- a/scene/2d/sprite.cpp +++ b/scene/2d/sprite.cpp @@ -322,8 +322,8 @@ void Sprite::_bind_methods() { ADD_PROPERTYNZ( PropertyInfo( Variant::VECTOR2, "offset"), _SCS("set_offset"),_SCS("get_offset")); ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "flip_h"), _SCS("set_flip_h"),_SCS("is_flipped_h")); ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "flip_v"), _SCS("set_flip_v"),_SCS("is_flipped_v")); - ADD_PROPERTYNO( PropertyInfo( Variant::INT, "vframes"), _SCS("set_vframes"),_SCS("get_vframes")); - ADD_PROPERTYNO( PropertyInfo( Variant::INT, "hframes"), _SCS("set_hframes"),_SCS("get_hframes")); + ADD_PROPERTYNO( PropertyInfo( Variant::INT, "vframes",PROPERTY_HINT_RANGE,"1,16384,1"), _SCS("set_vframes"),_SCS("get_vframes")); + ADD_PROPERTYNO( PropertyInfo( Variant::INT, "hframes",PROPERTY_HINT_RANGE,"1,16384,1"), _SCS("set_hframes"),_SCS("get_hframes")); ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame")); ADD_PROPERTYNO( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate")); ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "region"), _SCS("set_region"),_SCS("is_region")); diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index e9da95f3fb..c7d1249a07 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -578,8 +578,8 @@ void Sprite3D::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_hframes"),&Sprite3D::get_hframes); ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_texture"),_SCS("get_texture")); - ADD_PROPERTY( PropertyInfo( Variant::INT, "vframes"), _SCS("set_vframes"),_SCS("get_vframes")); - ADD_PROPERTY( PropertyInfo( Variant::INT, "hframes"), _SCS("set_hframes"),_SCS("get_hframes")); + ADD_PROPERTY( PropertyInfo( Variant::INT, "vframes",PROPERTY_HINT_RANGE,"1,16384,1"), _SCS("set_vframes"),_SCS("get_vframes")); + ADD_PROPERTY( PropertyInfo( Variant::INT, "hframes",PROPERTY_HINT_RANGE,"1,16384,1"), _SCS("set_hframes"),_SCS("get_hframes")); ADD_PROPERTY( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame")); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "region"), _SCS("set_region"),_SCS("is_region")); ADD_PROPERTY( PropertyInfo( Variant::RECT2, "region_rect"), _SCS("set_region_rect"),_SCS("get_region_rect")); diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index 41e775bbff..2478e3204c 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -27,7 +27,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "spin_box.h" - +#include "os/input.h" Size2 SpinBox::get_minimum_size() const { @@ -62,6 +62,13 @@ LineEdit *SpinBox::get_line_edit() { } +void SpinBox::_line_edit_input(const InputEvent& p_event) { + + + +} + + void SpinBox::_input_event(const InputEvent& p_event) { if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed) { @@ -94,6 +101,48 @@ void SpinBox::_input_event(const InputEvent& p_event) { } break; } } + + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed && p_event.mouse_button.button_index==1) { + + //set_default_cursor_shape(CURSOR_VSIZE); + Vector2 cpos = Vector2(p_event.mouse_button.x,p_event.mouse_button.y); + drag.mouse_pos=cpos; + } + + if (p_event.type==InputEvent::MOUSE_BUTTON && !p_event.mouse_button.pressed && p_event.mouse_button.button_index==1) { + + //set_default_cursor_shape(CURSOR_ARROW); + if (drag.enabled) { + drag.enabled=false; + Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); + warp_mouse(drag.capture_pos); + } + } + + if (p_event.type==InputEvent::MOUSE_MOTION && p_event.mouse_button.button_mask&1) { + + Vector2 cpos = Vector2(p_event.mouse_motion.x,p_event.mouse_motion.y); + if (drag.enabled) { + + float diff_y = drag.mouse_pos.y - cpos.y; + diff_y=pow(ABS(diff_y),1.8)*SGN(diff_y); + diff_y*=0.1; + + drag.mouse_pos=cpos; + drag.base_val=CLAMP(drag.base_val + get_step() * diff_y, get_min(), get_max()); + + set_val( drag.base_val); + + } else if (drag.mouse_pos.distance_to(cpos)>2) { + + Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED); + drag.enabled=true; + drag.base_val=get_val(); + drag.mouse_pos=cpos; + drag.capture_pos=cpos; + + } + } } @@ -177,6 +226,7 @@ void SpinBox::_bind_methods() { ObjectTypeDB::bind_method(_MD("is_editable"),&SpinBox::is_editable); ObjectTypeDB::bind_method(_MD("_line_edit_focus_exit"),&SpinBox::_line_edit_focus_exit); ObjectTypeDB::bind_method(_MD("get_line_edit"),&SpinBox::get_line_edit); + ObjectTypeDB::bind_method(_MD("_line_edit_input"),&SpinBox::_line_edit_input); ADD_PROPERTY(PropertyInfo(Variant::BOOL,"editable"),_SCS("set_editable"),_SCS("is_editable")); @@ -196,4 +246,6 @@ SpinBox::SpinBox() { //connect("value_changed",this,"_value_changed"); line_edit->connect("text_entered",this,"_text_entered",Vector(),CONNECT_DEFERRED); line_edit->connect("focus_exit",this,"_line_edit_focus_exit",Vector(),CONNECT_DEFERRED); + line_edit->connect("input_event",this,"_line_edit_input"); + drag.enabled=false; } diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h index 6ebe14631e..4c8cb8432a 100644 --- a/scene/gui/spin_box.h +++ b/scene/gui/spin_box.h @@ -44,6 +44,18 @@ class SpinBox : public Range { String prefix; String suffix; + void _line_edit_input(const InputEvent& p_event); + + + struct Drag { + float base_val; + bool enabled; + Vector2 from; + Vector2 mouse_pos; + Vector2 capture_pos; + } drag; + + void _line_edit_focus_exit(); protected: diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 4feb03feef..252414cb3e 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -31,7 +31,7 @@ #include "os/os.h" #include "os/keyboard.h" #include "globals.h" - +#include "os/input.h" @@ -70,6 +70,7 @@ Size2 TreeItem::Cell::get_icon_size() const { else return icon_region.size; } + void TreeItem::Cell::draw_icon(const RID& p_where, const Point2& p_pos, const Size2& p_size) const{ if (icon.is_null()) @@ -728,14 +729,20 @@ TreeItem::~TreeItem() { tree->root=0; } - if (tree && tree->popup_edited_item==this) + if (tree && tree->popup_edited_item==this) { tree->popup_edited_item=NULL; + tree->pressing_for_editor=false; + + } if (tree && tree->selected_item==this) tree->selected_item=NULL; - if (tree && tree->edited_item==this) + if (tree && tree->edited_item==this) { tree->edited_item=NULL; + tree->pressing_for_editor=false; + } + } @@ -1292,7 +1299,7 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col } else if (select_mode==SELECT_SINGLE || select_mode==SELECT_MULTI) { - if (&selected_cell==&c) { + if (!r_in_range && &selected_cell==&c) { if (!selected_cell.selected) { @@ -1301,6 +1308,7 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col selected_item=p_selected; selected_col=i; + emit_signal("cell_selected"); if (select_mode==SELECT_MULTI) emit_signal("multi_selected",p_current,i,true); @@ -1317,6 +1325,7 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col if (r_in_range && *r_in_range) { + if (!c.selected && c.selectable) { c.selected=true; emit_signal("multi_selected",p_current,i,true); @@ -1467,7 +1476,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ if (select_mode==SELECT_MULTI && p_mod.shift && selected_item && selected_item!=p_item) { bool inrange=false; - print_line("SELECT MULTI AND SHIFT AND ALL"); + select_single_item( p_item, root, col,selected_item,&inrange ); } else { select_single_item( p_item, root, col ); @@ -1490,7 +1499,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ /* editing */ - bool bring_up_editor=c.selected && already_selected; + bool bring_up_editor=c.selected;// && already_selected; bool bring_up_value_editor=false; String editor_text=c.text; @@ -1605,31 +1614,14 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ return -1; - click_handled=true; + + click_handled=true; popup_edited_item=p_item; popup_edited_item_col=col; - text_editor->set_pos(get_global_pos() + Point2i(col_ofs,_get_title_button_height()+y_ofs)-cache.offset ); - text_editor->set_size( Size2(col_width,item_h)); - text_editor->clear(); - text_editor->set_text( editor_text ); - text_editor->select_all(); - if (bring_up_value_editor) { - - value_editor->set_pos(get_global_pos() + Point2i(col_ofs,_get_title_button_height()+y_ofs)-cache.offset+Point2i(0,text_editor->get_size().height) ); - value_editor->set_size( Size2(col_width,1)); - value_editor->show_modal(); - updating_value_editor=true; - value_editor->set_min( c.min ); - value_editor->set_max( c.max ); - value_editor->set_step( c.step ); - value_editor->set_val( c.val ); - value_editor->set_exp_unit_value( c.expr ); - updating_value_editor=false; - } - - text_editor->show_modal(); - text_editor->grab_focus(); + pressing_item_rect=Rect2(get_global_pos() + Point2i(col_ofs,_get_title_button_height()+y_ofs)-cache.offset,Size2(col_width,item_h)); + pressing_for_editor_text=editor_text; + pressing_for_editor=true; return -1; //select } else { @@ -2062,6 +2054,33 @@ void Tree::_input_event(InputEvent p_event) { update(); } + if (pressing_for_editor && popup_edited_item && popup_edited_item->get_cell_mode(popup_edited_item_col)==TreeItem::CELL_MODE_RANGE) { + //range drag + + if (!range_drag_enabled) { + + Vector2 cpos = Vector2(b.x,b.y); + if (cpos.distance_to(pressing_pos)>2) { + range_drag_enabled=true; + range_drag_capture_pos=cpos; + range_drag_base=popup_edited_item->get_range(popup_edited_item_col); + Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED); + } + } else { + + TreeItem::Cell &c=popup_edited_item->cells[popup_edited_item_col]; + float diff_y = -b.relative_y; + diff_y=pow(ABS(diff_y),1.8)*SGN(diff_y); + diff_y*=0.1; + range_drag_base=CLAMP(range_drag_base + c.step * diff_y, c.min, c.max); + + popup_edited_item->set_range(popup_edited_item_col,range_drag_base); + item_edited(popup_edited_item_col,popup_edited_item); + + } + + } + if (drag_touching && ! drag_touching_deaccel) { @@ -2084,6 +2103,31 @@ void Tree::_input_event(InputEvent p_event) { if (b.button_index==BUTTON_LEFT) { + if (pressing_for_editor) { + + if (range_drag_enabled) { + + range_drag_enabled=false; + Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); + warp_mouse(range_drag_capture_pos); + } else { + text_editor->set_pos(pressing_item_rect.pos); + text_editor->set_size(pressing_item_rect.size); + + text_editor->clear(); + text_editor->set_text( pressing_for_editor_text ); + text_editor->select_all(); + + text_editor->show_modal(); + text_editor->grab_focus(); + + } + pressing_for_editor=false; + + } + + + if (cache.click_type==Cache::CLICK_BUTTON) { emit_signal("button_pressed",cache.click_item,cache.click_column,cache.click_id); @@ -2145,11 +2189,15 @@ void Tree::_input_event(InputEvent p_event) { break; click_handled=false; + pressing_for_editor=false; blocked++; bool handled = propagate_mouse_event(pos+cache.offset,0,0,b.doubleclick,root,b.button_index,b.mod); blocked--; + if (pressing_for_editor) { + pressing_pos=Point2(b.x,b.y); + } if (drag_touching) { @@ -2615,6 +2663,8 @@ void Tree::clear() { selected_item=NULL; edited_item=NULL; popup_edited_item=NULL; + selected_item=NULL; + pressing_for_editor=false; update(); }; @@ -3189,6 +3239,8 @@ Tree::Tree() { drag_speed=0; drag_touching=false; drag_touching_deaccel=false; + pressing_for_editor=false; + range_drag_enabled=false; } diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 8ddddd0630..3fbd7c95d9 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -258,7 +258,18 @@ friend class TreeItem; TreeItem *popup_edited_item; TreeItem *selected_item; TreeItem *edited_item; + + int pressed_button; + bool pressing_for_editor; + String pressing_for_editor_text; + Vector2 pressing_pos; + Rect2 pressing_item_rect; + + float range_drag_base; + bool range_drag_enabled; + Vector2 range_drag_capture_pos; + //TreeItem *cursor_item; //int cursor_column; diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 3ee4da5974..5a99538a5f 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -297,7 +297,7 @@ void make_default_theme() { t->set_color("font_color_hover","MenuButton", control_font_color_hover ); t->set_color("font_color_disabled","MenuButton", Color(1,1,1,0.3) ); - t->set_constant("hseparation","MenuButton", 0 ); + t->set_constant("hseparation","MenuButton", 3 ); // CheckBox diff --git a/tools/editor/array_property_edit.cpp b/tools/editor/array_property_edit.cpp new file mode 100644 index 0000000000..9cd443270b --- /dev/null +++ b/tools/editor/array_property_edit.cpp @@ -0,0 +1,231 @@ +#include "array_property_edit.h" + +#include "editor_node.h" + +#define ITEMS_PER_PAGE 100 + +Variant ArrayPropertyEdit::get_array() const{ + + Object*o = ObjectDB::get_instance(obj); + if (!o) + return Array(); + Variant arr=o->get(property); + if (!arr.is_array()) { + Variant::CallError ce; + arr=Variant::construct(default_type,NULL,0,ce); + } + return arr; +} + +void ArrayPropertyEdit::_notif_change() { + _change_notify(); +} +void ArrayPropertyEdit::_notif_changev(const String& p_v) { + + _change_notify(p_v.utf8().get_data()); +} + +void ArrayPropertyEdit::_set_size(int p_size) { + + Variant arr = get_array(); + arr.call("resize",p_size); + Object*o = ObjectDB::get_instance(obj); + if (!o) + return; + + o->set(property,arr); + +} + +void ArrayPropertyEdit::_set_value(int p_idx,const Variant& p_value) { + + Variant arr = get_array(); + arr.set(p_idx,p_value); + Object*o = ObjectDB::get_instance(obj); + if (!o) + return; + + o->set(property,arr); +} + +bool ArrayPropertyEdit::_set(const StringName& p_name, const Variant& p_value){ + + String pn=p_name; + + if (pn.begins_with("array/")) { + + if (pn=="array/size") { + + Variant arr = get_array(); + int size = arr.call("size"); + + int newsize=p_value; + if (newsize==size) + return true; + + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Resize Array"); + ur->add_do_method(this,"_set_size",newsize); + ur->add_undo_method(this,"_set_size",size); + if (newsizeadd_undo_method(this,"_set_value",i,arr.get(i)); + + } + } + ur->add_do_method(this,"_notif_change"); + ur->add_undo_method(this,"_notif_change"); + ur->commit_action(); + return true; + } + if (pn=="array/page") { + page=p_value; + _change_notify(); + return true; + } + } else if (pn.begins_with("indices")) { + + if (pn.find("_")!=-1) { + //type + int idx=pn.get_slicec('/',1).get_slicec('_',0).to_int(); + + int type = p_value; + + Variant arr = get_array(); + + Variant value = arr.get(idx); + if (value.get_type()!=type && type>=0 && typeget_undo_redo(); + + ur->create_action("Change Array Value Type"); + ur->add_do_method(this,"_set_value",idx,new_value); + ur->add_undo_method(this,"_set_value",idx,value); + ur->add_do_method(this,"_notif_change"); + ur->add_undo_method(this,"_notif_change"); + ur->commit_action(); + + } + return true; + + } else { + int idx=pn.get_slicec('/',1).to_int(); + Variant arr = get_array(); + + Variant value = arr.get(idx); + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + + ur->create_action("Change Array Value"); + ur->add_do_method(this,"_set_value",idx,p_value); + ur->add_undo_method(this,"_set_value",idx,value); + ur->add_do_method(this,"_notif_changev",p_name); + ur->add_undo_method(this,"_notif_changev",p_name); + ur->commit_action(); + return true; + } + } + + return false; +} + +bool ArrayPropertyEdit::_get(const StringName& p_name,Variant &r_ret) const { + + Variant arr = get_array(); + //int size = arr.call("size"); + + String pn=p_name; + if (pn.begins_with("array/")) { + + if (pn=="array/size") { + r_ret=arr.call("size"); + return true; + } + if (pn=="array/page") { + r_ret=page; + return true; + } + } else if (pn.begins_with("indices")) { + + if (pn.find("_")!=-1) { + //type + int idx=pn.get_slicec('/',1).get_slicec('_',0).to_int(); + bool valid; + r_ret=arr.get(idx,&valid); + if (valid) + r_ret=r_ret.get_type(); + return valid; + + } else { + int idx=pn.get_slicec('/',1).to_int(); + bool valid; + r_ret=arr.get(idx,&valid); + return valid; + } + } + + return false; +} + +void ArrayPropertyEdit::_get_property_list( List *p_list) const{ + + Variant arr = get_array(); + int size = arr.call("size"); + + p_list->push_back( PropertyInfo(Variant::INT,"array/size",PROPERTY_HINT_RANGE,"0,100000,1") ); + int pages = size/ITEMS_PER_PAGE; + if (pages>0) + p_list->push_back( PropertyInfo(Variant::INT,"array/page",PROPERTY_HINT_RANGE,"0,"+itos(pages)+",1") ); + + int offset=page*ITEMS_PER_PAGE; + + int items=MIN(size-offset,ITEMS_PER_PAGE); + + + for(int i=0;ipush_back(PropertyInfo(Variant::INT,"indices/"+itos(i+offset)+"_type",PROPERTY_HINT_ENUM,vtypes)); + } + if (arr.get_type()!=Variant::ARRAY || v.get_type()!=Variant::NIL) { + PropertyInfo pi(v.get_type(),"indices/"+itos(i+offset)); + if (v.get_type()==Variant::OBJECT) { + pi.hint=PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string="Resource"; + } + p_list->push_back(pi); + } + } + +} + +void ArrayPropertyEdit::edit(Object* p_obj,const StringName& p_prop,Variant::Type p_deftype) { + + page=0; + property=p_prop; + obj=p_obj->get_instance_ID(); + default_type=p_deftype; + +} + +void ArrayPropertyEdit::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("_set_size"),&ArrayPropertyEdit::_set_size); + ObjectTypeDB::bind_method(_MD("_set_value"),&ArrayPropertyEdit::_set_value); + ObjectTypeDB::bind_method(_MD("_notif_change"),&ArrayPropertyEdit::_notif_change); + ObjectTypeDB::bind_method(_MD("_notif_changev"),&ArrayPropertyEdit::_notif_changev); +} + +ArrayPropertyEdit::ArrayPropertyEdit() +{ + page=0; + for(int i=0;i0) + vtypes+=","; + vtypes+=Variant::get_type_name( Variant::Type(i) ); + } + default_type=Variant::NIL; + +} diff --git a/tools/editor/array_property_edit.h b/tools/editor/array_property_edit.h new file mode 100644 index 0000000000..acfb8e68ed --- /dev/null +++ b/tools/editor/array_property_edit.h @@ -0,0 +1,36 @@ +#ifndef ARRAY_PROPERTY_EDIT_H +#define ARRAY_PROPERTY_EDIT_H + +#include "scene/main/node.h" + +class ArrayPropertyEdit : public Reference { + + OBJ_TYPE(ArrayPropertyEdit,Reference); + + int page; + ObjectID obj; + StringName property; + String vtypes; + Variant get_array() const; + Variant::Type default_type; + + void _notif_change(); + void _notif_changev(const String& p_v); + void _set_size(int p_size); + void _set_value(int p_idx,const Variant& p_value); + +protected: + + static void _bind_methods(); + 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 *p_list) const; + +public: + + void edit(Object* p_obj, const StringName& p_prop, Variant::Type p_deftype); + + ArrayPropertyEdit(); +}; + +#endif // ARRAY_PROPERTY_EDIT_H diff --git a/tools/editor/editor_data.cpp b/tools/editor/editor_data.cpp index ac68fcb07b..3131bd895c 100644 --- a/tools/editor/editor_data.cpp +++ b/tools/editor/editor_data.cpp @@ -523,7 +523,7 @@ Ref