-fixes to capture mode

-ability to drag spinboxes and tree ranges to change values, like in Unity or Unreal
This commit is contained in:
Juan Linietsky 2015-08-29 01:43:21 -03:00
parent b0be30d9ef
commit 3a59747c62
6 changed files with 204 additions and 29 deletions

View file

@ -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.

View file

@ -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;

View file

@ -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<Variant>(),CONNECT_DEFERRED);
line_edit->connect("focus_exit",this,"_line_edit_focus_exit",Vector<Variant>(),CONNECT_DEFERRED);
line_edit->connect("input_event",this,"_line_edit_input");
drag.enabled=false;
}

View file

@ -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:

View file

@ -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;
}
}
@ -1490,7 +1497,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 +1612,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 +2052,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 +2101,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 +2187,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 +2661,8 @@ void Tree::clear() {
selected_item=NULL;
edited_item=NULL;
popup_edited_item=NULL;
selected_item=NULL;
pressing_for_editor=false;
update();
};
@ -3189,6 +3237,8 @@ Tree::Tree() {
drag_speed=0;
drag_touching=false;
drag_touching_deaccel=false;
pressing_for_editor=false;
range_drag_enabled=false;
}

View file

@ -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;