-begun implementing drag & drop editor wide
-filesystem dock dnd support -property list dnd support -scene tree dnd support
This commit is contained in:
parent
41db10a8ae
commit
d7318f6965
20 changed files with 1120 additions and 37 deletions
|
@ -1044,8 +1044,7 @@ void ItemList::_scroll_changed(double) {
|
|||
update();
|
||||
}
|
||||
|
||||
|
||||
String ItemList::get_tooltip(const Point2& p_pos) const {
|
||||
int ItemList::get_item_at_pos(const Point2& p_pos) const {
|
||||
|
||||
Vector2 pos=p_pos;
|
||||
Ref<StyleBox> bg = get_stylebox("bg");
|
||||
|
@ -1074,6 +1073,13 @@ String ItemList::get_tooltip(const Point2& p_pos) const {
|
|||
}
|
||||
}
|
||||
|
||||
return closest;
|
||||
}
|
||||
|
||||
String ItemList::get_tooltip(const Point2& p_pos) const {
|
||||
|
||||
int closest = get_item_at_pos(p_pos);
|
||||
|
||||
if (closest!=-1) {
|
||||
if (items[closest].tooltip!="") {
|
||||
return items[closest].tooltip;
|
||||
|
@ -1084,8 +1090,6 @@ String ItemList::get_tooltip(const Point2& p_pos) const {
|
|||
}
|
||||
|
||||
return Control::get_tooltip(p_pos);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ItemList::sort_items_by_text() {
|
||||
|
@ -1170,6 +1174,8 @@ void ItemList::_bind_methods(){
|
|||
ObjectTypeDB::bind_method(_MD("set_min_icon_size","size"),&ItemList::set_min_icon_size);
|
||||
ObjectTypeDB::bind_method(_MD("get_min_icon_size"),&ItemList::get_min_icon_size);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("get_item_at_pos","pos"),&ItemList::get_item_at_pos);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("ensure_current_is_visible"),&ItemList::ensure_current_is_visible);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_scroll_changed"),&ItemList::_scroll_changed);
|
||||
|
|
|
@ -140,6 +140,7 @@ public:
|
|||
int find_metadata(const Variant& p_metadata) const;
|
||||
|
||||
virtual String get_tooltip(const Point2& p_pos) const;
|
||||
int get_item_at_pos(const Point2& p_pos) const;
|
||||
|
||||
ItemList();
|
||||
~ItemList();
|
||||
|
|
|
@ -604,10 +604,11 @@ String TreeItem::get_tooltip(int p_column) const{
|
|||
return cells[p_column].tooltip;
|
||||
}
|
||||
|
||||
void TreeItem::set_custom_bg_color(int p_column,const Color& p_color) {
|
||||
void TreeItem::set_custom_bg_color(int p_column,const Color& p_color,bool p_bg_outline) {
|
||||
|
||||
ERR_FAIL_INDEX( p_column, cells.size() );
|
||||
cells[p_column].custom_bg_color=true;
|
||||
cells[p_column].custom_bg_outline=p_bg_outline;
|
||||
cells[p_column].bg_color=p_color;
|
||||
_changed_notify(p_column);
|
||||
}
|
||||
|
@ -685,7 +686,7 @@ void TreeItem::_bind_methods() {
|
|||
ObjectTypeDB::bind_method(_MD("set_custom_color","column","color"),&TreeItem::set_custom_color);
|
||||
ObjectTypeDB::bind_method(_MD("clear_custom_color","column"),&TreeItem::clear_custom_color);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_custom_bg_color","column","color"),&TreeItem::set_custom_bg_color);
|
||||
ObjectTypeDB::bind_method(_MD("set_custom_bg_color","column","color","just_outline"),&TreeItem::set_custom_bg_color,DEFVAL(false));
|
||||
ObjectTypeDB::bind_method(_MD("clear_custom_bg_color","column"),&TreeItem::clear_custom_bg_color);
|
||||
ObjectTypeDB::bind_method(_MD("get_custom_bg_color","column"),&TreeItem::get_custom_bg_color);
|
||||
|
||||
|
@ -757,6 +758,13 @@ TreeItem::~TreeItem() {
|
|||
if (tree && tree->selected_item==this)
|
||||
tree->selected_item=NULL;
|
||||
|
||||
|
||||
if (tree && tree->drop_mode_over==this)
|
||||
tree->drop_mode_over=NULL;
|
||||
|
||||
if (tree && tree->single_select_defer==this)
|
||||
tree->single_select_defer=NULL;
|
||||
|
||||
if (tree && tree->edited_item==this) {
|
||||
tree->edited_item=NULL;
|
||||
tree->pressing_for_editor=false;
|
||||
|
@ -797,17 +805,13 @@ void Tree::update_cache() {
|
|||
cache.font_color=get_color("font_color");
|
||||
cache.font_color_selected=get_color("font_color_selected");
|
||||
cache.guide_color=get_color("guide_color");
|
||||
cache.drop_position_color=get_color("drop_position_color");
|
||||
cache.hseparation=get_constant("hseparation");
|
||||
cache.vseparation=get_constant("vseparation");
|
||||
cache.item_margin=get_constant("item_margin");
|
||||
cache.button_margin=get_constant("button_margin");
|
||||
cache.guide_width=get_constant("guide_width");
|
||||
|
||||
Ref<StyleBox> title_button;
|
||||
Ref<StyleBox> title_button_hover;
|
||||
Ref<StyleBox> title_button_pressed;
|
||||
Color title_button_color;
|
||||
|
||||
cache.title_button = get_stylebox("title_button_normal");
|
||||
cache.title_button_pressed = get_stylebox("title_button_pressed");
|
||||
cache.title_button_hover = get_stylebox("title_button_hover");
|
||||
|
@ -1087,7 +1091,34 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2&
|
|||
Rect2 r=cell_rect;
|
||||
r.pos.x-=cache.hseparation;
|
||||
r.size.x+=cache.hseparation;
|
||||
VisualServer::get_singleton()->canvas_item_add_rect(ci,r,p_item->cells[i].bg_color);
|
||||
if (p_item->cells[i].custom_bg_outline) {
|
||||
VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(r.pos.x,r.pos.y,r.size.x,1),p_item->cells[i].bg_color);
|
||||
VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(r.pos.x,r.pos.y+r.size.y-1,r.size.x,1),p_item->cells[i].bg_color);
|
||||
VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(r.pos.x,r.pos.y,1,r.size.y),p_item->cells[i].bg_color);
|
||||
VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(r.pos.x+r.size.x-1,r.pos.y,1,r.size.y),p_item->cells[i].bg_color);
|
||||
} else {
|
||||
VisualServer::get_singleton()->canvas_item_add_rect(ci,r,p_item->cells[i].bg_color);
|
||||
}
|
||||
}
|
||||
|
||||
if (drop_mode_flags && drop_mode_over==p_item) {
|
||||
|
||||
Rect2 r=cell_rect;
|
||||
|
||||
if (drop_mode_section==-1 || drop_mode_section==0) {
|
||||
VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(r.pos.x,r.pos.y,r.size.x,1),cache.drop_position_color);
|
||||
|
||||
}
|
||||
|
||||
if (drop_mode_section==0) {
|
||||
VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(r.pos.x,r.pos.y,1,r.size.y),cache.drop_position_color);
|
||||
VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(r.pos.x+r.size.x-1,r.pos.y,1,r.size.y),cache.drop_position_color);
|
||||
|
||||
}
|
||||
|
||||
if (drop_mode_section==1 || drop_mode_section==0) {
|
||||
VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(r.pos.x,r.pos.y+r.size.y,r.size.x,1),cache.drop_position_color);
|
||||
}
|
||||
}
|
||||
|
||||
Color col=p_item->cells[i].custom_color?p_item->cells[i].color:get_color( p_item->cells[i].selected?"font_color_selected":"font_color");
|
||||
|
@ -1280,6 +1311,25 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2&
|
|||
|
||||
}
|
||||
|
||||
int Tree::_count_selected_items(TreeItem* p_from) const {
|
||||
|
||||
int count=0;
|
||||
for(int i=0;i<columns.size();i++) {
|
||||
if (p_from->is_selected(i))
|
||||
count++;
|
||||
}
|
||||
|
||||
if (p_from->get_children()) {
|
||||
count+=_count_selected_items(p_from->get_children());
|
||||
}
|
||||
|
||||
if (p_from->get_next()) {
|
||||
count+=_count_selected_items(p_from->get_next());
|
||||
}
|
||||
|
||||
return count;
|
||||
|
||||
}
|
||||
void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col,TreeItem *p_prev,bool *r_in_range) {
|
||||
|
||||
TreeItem::Cell &selected_cell=p_selected->cells[p_col];
|
||||
|
@ -1548,7 +1598,15 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_
|
|||
|
||||
select_single_item( p_item, root, col,selected_item,&inrange );
|
||||
} else {
|
||||
select_single_item( p_item, root, col );
|
||||
|
||||
int icount = _count_selected_items(root);
|
||||
|
||||
if (select_mode==SELECT_MULTI && icount>1) {
|
||||
single_select_defer=p_item;
|
||||
single_select_defer_column=col;
|
||||
} else {
|
||||
select_single_item( p_item, root, col );
|
||||
}
|
||||
}
|
||||
|
||||
//if (!c.selected && select_mode==SELECT_MULTI) {
|
||||
|
@ -2159,6 +2217,31 @@ void Tree::_input_event(InputEvent p_event) {
|
|||
|
||||
}
|
||||
|
||||
if (drop_mode_flags && root) {
|
||||
|
||||
Point2 mpos=Point2(b.x,b.y);
|
||||
mpos -= cache.bg->get_offset();
|
||||
mpos.y-=_get_title_button_height();
|
||||
if (mpos.y>=0) {
|
||||
|
||||
if (h_scroll->is_visible())
|
||||
mpos.x+=h_scroll->get_val();
|
||||
if (v_scroll->is_visible())
|
||||
mpos.y+=v_scroll->get_val();
|
||||
|
||||
int col,h,section;
|
||||
TreeItem *it = _find_item_at_pos(root,mpos,col,h,section);
|
||||
|
||||
if (it!=drop_mode_over || section!=drop_mode_section) {
|
||||
drop_mode_over=it;
|
||||
drop_mode_section=section;
|
||||
update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (cache.hover_type!=old_hover || cache.hover_index!=old_index) {
|
||||
update();
|
||||
}
|
||||
|
@ -2211,6 +2294,12 @@ void Tree::_input_event(InputEvent p_event) {
|
|||
|
||||
if (b.button_index==BUTTON_LEFT) {
|
||||
|
||||
|
||||
if (single_select_defer) {
|
||||
select_single_item( single_select_defer, root, single_select_defer_column );
|
||||
single_select_defer=NULL;
|
||||
}
|
||||
|
||||
range_click_timer->stop();
|
||||
|
||||
if (pressing_for_editor) {
|
||||
|
@ -2522,6 +2611,15 @@ void Tree::_notification(int p_what) {
|
|||
|
||||
update_cache();;
|
||||
}
|
||||
if (p_what==NOTIFICATION_DRAG_END) {
|
||||
|
||||
drop_mode_flags=0;
|
||||
update();
|
||||
}
|
||||
if (p_what==NOTIFICATION_DRAG_BEGIN) {
|
||||
|
||||
single_select_defer=NULL;
|
||||
}
|
||||
if (p_what==NOTIFICATION_FIXED_PROCESS) {
|
||||
|
||||
if (drag_touching) {
|
||||
|
@ -3135,7 +3233,7 @@ void Tree::_do_incr_search(const String& p_add) {
|
|||
|
||||
}
|
||||
|
||||
TreeItem* Tree::_find_item_at_pos(TreeItem*p_item, const Point2& p_pos,int& r_column,int &h) const {
|
||||
TreeItem* Tree::_find_item_at_pos(TreeItem*p_item, const Point2& p_pos,int& r_column,int &h,int §ion) const {
|
||||
|
||||
Point2 pos = p_pos;
|
||||
|
||||
|
@ -3145,15 +3243,33 @@ TreeItem* Tree::_find_item_at_pos(TreeItem*p_item, const Point2& p_pos,int& r_co
|
|||
h = compute_item_height(p_item)+cache.vseparation;;
|
||||
if (pos.y<h) {
|
||||
|
||||
if (drop_mode_flags==DROP_MODE_ON_ITEM) {
|
||||
section=0;
|
||||
} else if (drop_mode_flags==DROP_MODE_INBETWEEN) {
|
||||
section=pos.y<h/2?-1:1;
|
||||
} else if (pos.y<h/4) {
|
||||
section=-1;
|
||||
} else if (pos.y>=(h*3/4)) {
|
||||
section=1;
|
||||
} else {
|
||||
section=0;
|
||||
}
|
||||
|
||||
for(int i=0;i<columns.size();i++) {
|
||||
|
||||
int w = get_column_width(i);
|
||||
if (pos.x < w) {
|
||||
r_column=i;
|
||||
|
||||
|
||||
return p_item;
|
||||
}
|
||||
pos.x-=w;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return NULL;
|
||||
} else {
|
||||
|
||||
|
@ -3172,7 +3288,7 @@ TreeItem* Tree::_find_item_at_pos(TreeItem*p_item, const Point2& p_pos,int& r_co
|
|||
|
||||
|
||||
int ch;
|
||||
TreeItem *r = _find_item_at_pos(n,pos,r_column,ch);
|
||||
TreeItem *r = _find_item_at_pos(n,pos,r_column,ch,section);
|
||||
pos.y-=ch;
|
||||
h+=ch;
|
||||
if (r)
|
||||
|
@ -3184,6 +3300,88 @@ TreeItem* Tree::_find_item_at_pos(TreeItem*p_item, const Point2& p_pos,int& r_co
|
|||
|
||||
}
|
||||
|
||||
int Tree::get_column_at_pos(const Point2& p_pos) const {
|
||||
|
||||
if (root) {
|
||||
|
||||
Point2 pos=p_pos;
|
||||
pos -= cache.bg->get_offset();
|
||||
pos.y-=_get_title_button_height();
|
||||
if (pos.y<0)
|
||||
return -1;
|
||||
|
||||
if (h_scroll->is_visible())
|
||||
pos.x+=h_scroll->get_val();
|
||||
if (v_scroll->is_visible())
|
||||
pos.y+=v_scroll->get_val();
|
||||
|
||||
int col,h,section;
|
||||
TreeItem *it = _find_item_at_pos(root,pos,col,h,section);
|
||||
|
||||
if (it) {
|
||||
return col;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
int Tree::get_drop_section_at_pos(const Point2& p_pos) const {
|
||||
|
||||
if (root) {
|
||||
|
||||
Point2 pos=p_pos;
|
||||
pos -= cache.bg->get_offset();
|
||||
pos.y-=_get_title_button_height();
|
||||
if (pos.y<0)
|
||||
return -100;
|
||||
|
||||
if (h_scroll->is_visible())
|
||||
pos.x+=h_scroll->get_val();
|
||||
if (v_scroll->is_visible())
|
||||
pos.y+=v_scroll->get_val();
|
||||
|
||||
int col,h,section;
|
||||
TreeItem *it = _find_item_at_pos(root,pos,col,h,section);
|
||||
|
||||
if (it) {
|
||||
return section;
|
||||
}
|
||||
}
|
||||
|
||||
return -100;
|
||||
|
||||
}
|
||||
TreeItem* Tree::get_item_at_pos(const Point2& p_pos) const {
|
||||
|
||||
|
||||
if (root) {
|
||||
|
||||
Point2 pos=p_pos;
|
||||
pos -= cache.bg->get_offset();
|
||||
pos.y-=_get_title_button_height();
|
||||
if (pos.y<0)
|
||||
return NULL;
|
||||
|
||||
if (h_scroll->is_visible())
|
||||
pos.x+=h_scroll->get_val();
|
||||
if (v_scroll->is_visible())
|
||||
pos.y+=v_scroll->get_val();
|
||||
|
||||
int col,h,section;
|
||||
TreeItem *it = _find_item_at_pos(root,pos,col,h,section);
|
||||
|
||||
if (it) {
|
||||
|
||||
return it;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
String Tree::get_tooltip(const Point2& p_pos) const {
|
||||
|
||||
if (root) {
|
||||
|
@ -3199,8 +3397,8 @@ String Tree::get_tooltip(const Point2& p_pos) const {
|
|||
if (v_scroll->is_visible())
|
||||
pos.y+=v_scroll->get_val();
|
||||
|
||||
int col,h;
|
||||
TreeItem *it = _find_item_at_pos(root,pos,col,h);
|
||||
int col,h,section;
|
||||
TreeItem *it = _find_item_at_pos(root,pos,col,h,section);
|
||||
|
||||
|
||||
if (it) {
|
||||
|
@ -3241,6 +3439,20 @@ void Tree::set_value_evaluator(ValueEvaluator *p_evaluator) {
|
|||
evaluator = p_evaluator;
|
||||
}
|
||||
|
||||
void Tree::set_drop_mode_flags(int p_flags) {
|
||||
drop_mode_flags=p_flags;
|
||||
if (drop_mode_flags==0) {
|
||||
drop_mode_over=NULL;
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
int Tree::get_drop_mode_flags() const {
|
||||
|
||||
return drop_mode_flags;
|
||||
}
|
||||
|
||||
void Tree::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_range_click_timeout"),&Tree::_range_click_timeout);
|
||||
|
@ -3273,6 +3485,8 @@ void Tree::_bind_methods() {
|
|||
ObjectTypeDB::bind_method(_MD("get_edited_column"),&Tree::get_edited_column);
|
||||
ObjectTypeDB::bind_method(_MD("get_custom_popup_rect"),&Tree::get_custom_popup_rect);
|
||||
ObjectTypeDB::bind_method(_MD("get_item_area_rect","item:TreeItem","column"),&Tree::_get_item_rect,DEFVAL(-1));
|
||||
ObjectTypeDB::bind_method(_MD("get_item_at_pos:TreeItem","pos"),&Tree::get_item_at_pos);
|
||||
ObjectTypeDB::bind_method(_MD("get_column_at_pos","pos"),&Tree::get_column_at_pos);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("ensure_cursor_is_visible"),&Tree::ensure_cursor_is_visible);
|
||||
|
||||
|
@ -3286,6 +3500,9 @@ void Tree::_bind_methods() {
|
|||
ObjectTypeDB::bind_method(_MD("set_hide_folding","hide"),&Tree::set_hide_folding);
|
||||
ObjectTypeDB::bind_method(_MD("is_folding_hidden"),&Tree::is_folding_hidden);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_drop_mode_flags","flags"),&Tree::set_drop_mode_flags);
|
||||
ObjectTypeDB::bind_method(_MD("get_drop_mode_flags"),&Tree::get_drop_mode_flags);
|
||||
|
||||
|
||||
ADD_SIGNAL( MethodInfo("item_selected"));
|
||||
ADD_SIGNAL( MethodInfo("cell_selected"));
|
||||
|
@ -3300,6 +3517,11 @@ void Tree::_bind_methods() {
|
|||
BIND_CONSTANT( SELECT_SINGLE );
|
||||
BIND_CONSTANT( SELECT_ROW );
|
||||
BIND_CONSTANT( SELECT_MULTI );
|
||||
|
||||
BIND_CONSTANT( DROP_MODE_DISABLED );
|
||||
BIND_CONSTANT( DROP_MODE_ON_ITEM );
|
||||
BIND_CONSTANT( DROP_MODE_INBETWEEN );
|
||||
|
||||
}
|
||||
|
||||
Tree::Tree() {
|
||||
|
@ -3381,6 +3603,11 @@ Tree::Tree() {
|
|||
hide_folding=false;
|
||||
|
||||
evaluator=NULL;
|
||||
|
||||
drop_mode_flags=0;
|
||||
drop_mode_over=NULL;
|
||||
drop_mode_section=0;
|
||||
single_select_defer=NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -79,7 +79,9 @@ friend class Tree;
|
|||
bool custom_color;
|
||||
Color color;
|
||||
bool custom_bg_color;
|
||||
bool custom_bg_outline;
|
||||
Color bg_color;
|
||||
|
||||
Variant meta;
|
||||
String tooltip;
|
||||
|
||||
|
@ -226,7 +228,7 @@ public:
|
|||
Color get_custom_color(int p_column) const;
|
||||
void clear_custom_color(int p_column);
|
||||
|
||||
void set_custom_bg_color(int p_column,const Color& p_color);
|
||||
void set_custom_bg_color(int p_column, const Color& p_color, bool p_bg_outline=false);
|
||||
void clear_custom_bg_color(int p_column);
|
||||
Color get_custom_bg_color(int p_column) const;
|
||||
|
||||
|
@ -257,6 +259,12 @@ public:
|
|||
SELECT_MULTI
|
||||
};
|
||||
|
||||
enum DropModeFlags {
|
||||
DROP_MODE_DISABLED=0,
|
||||
DROP_MODE_ON_ITEM=1,
|
||||
DROP_MODE_INBETWEEN=2
|
||||
};
|
||||
|
||||
private:
|
||||
friend class TreeItem;
|
||||
|
||||
|
@ -265,6 +273,11 @@ friend class TreeItem;
|
|||
TreeItem *selected_item;
|
||||
TreeItem *edited_item;
|
||||
|
||||
TreeItem *drop_mode_over;
|
||||
int drop_mode_section;
|
||||
|
||||
TreeItem *single_select_defer;
|
||||
int single_select_defer_column;
|
||||
|
||||
int pressed_button;
|
||||
bool pressing_for_editor;
|
||||
|
@ -289,6 +302,8 @@ friend class TreeItem;
|
|||
|
||||
int blocked;
|
||||
|
||||
int drop_mode_flags;
|
||||
|
||||
struct ColumnInfo {
|
||||
|
||||
int min_width;
|
||||
|
@ -361,6 +376,8 @@ friend class TreeItem;
|
|||
Color font_color;
|
||||
Color font_color_selected;
|
||||
Color guide_color;
|
||||
Color drop_position_color;
|
||||
|
||||
int hseparation;
|
||||
int vseparation;
|
||||
int item_margin;
|
||||
|
@ -405,7 +422,7 @@ friend class TreeItem;
|
|||
|
||||
TreeItem* _search_item_text(TreeItem *p_at, const String& p_find,int *r_col,bool p_selectable,bool p_backwards=false);
|
||||
|
||||
TreeItem* _find_item_at_pos(TreeItem *p_current, const Point2& p_pos,int& r_column,int &h) const;
|
||||
TreeItem* _find_item_at_pos(TreeItem *p_current, const Point2& p_pos, int& r_column, int &h, int §ion) const;
|
||||
|
||||
/* float drag_speed;
|
||||
float drag_accum;
|
||||
|
@ -426,6 +443,8 @@ friend class TreeItem;
|
|||
|
||||
ValueEvaluator *evaluator;
|
||||
|
||||
int _count_selected_items(TreeItem* p_from) const;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
|
@ -433,10 +452,16 @@ protected:
|
|||
Object* _create_item(Object *p_parent) { return create_item(p_parent->cast_to<TreeItem>() ); }
|
||||
TreeItem *_get_next_selected(Object *p_item) { return get_next_selected(p_item->cast_to<TreeItem>() ); }
|
||||
Rect2 _get_item_rect(Object *p_item,int p_column) const { return get_item_rect(p_item->cast_to<TreeItem>(),p_column ); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
virtual String get_tooltip(const Point2& p_pos) const;
|
||||
|
||||
TreeItem* get_item_at_pos(const Point2& p_pos) const;
|
||||
int get_column_at_pos(const Point2& p_pos) const;
|
||||
int get_drop_section_at_pos(const Point2& p_pos) const;
|
||||
|
||||
void clear();
|
||||
|
||||
TreeItem* create_item(TreeItem *p_parent=0);
|
||||
|
@ -486,6 +511,9 @@ public:
|
|||
void set_hide_folding(bool p_hide);
|
||||
bool is_folding_hidden() const;
|
||||
|
||||
void set_drop_mode_flags(int p_flags);
|
||||
int get_drop_mode_flags() const;
|
||||
|
||||
void set_value_evaluator(ValueEvaluator *p_evaluator);
|
||||
|
||||
Tree();
|
||||
|
|
|
@ -2095,6 +2095,8 @@ void Node::_bind_methods() {
|
|||
BIND_CONSTANT( NOTIFICATION_PAUSED );
|
||||
BIND_CONSTANT( NOTIFICATION_UNPAUSED );
|
||||
BIND_CONSTANT( NOTIFICATION_INSTANCED );
|
||||
BIND_CONSTANT( NOTIFICATION_DRAG_BEGIN );
|
||||
BIND_CONSTANT( NOTIFICATION_DRAG_END );
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -180,6 +180,8 @@ public:
|
|||
NOTIFICATION_PARENTED=18,
|
||||
NOTIFICATION_UNPARENTED=19,
|
||||
NOTIFICATION_INSTANCED=20,
|
||||
NOTIFICATION_DRAG_BEGIN=21,
|
||||
NOTIFICATION_DRAG_END=22,
|
||||
};
|
||||
|
||||
/* NODE/TREE */
|
||||
|
|
|
@ -985,6 +985,16 @@ void Viewport::_propagate_enter_world(Node *p_node) {
|
|||
}
|
||||
}
|
||||
|
||||
void Viewport::_propagate_viewport_notification(Node* p_node,int p_what) {
|
||||
|
||||
p_node->notification(p_what);
|
||||
for(int i=0;i<p_node->get_child_count();i++) {
|
||||
Node *c = p_node->get_child(i);
|
||||
if (c->cast_to<Viewport>())
|
||||
continue;
|
||||
_propagate_viewport_notification(c,p_what);
|
||||
}
|
||||
}
|
||||
|
||||
void Viewport::_propagate_exit_world(Node *p_node) {
|
||||
|
||||
|
@ -1676,6 +1686,9 @@ void Viewport::_gui_input_event(InputEvent p_event) {
|
|||
if (p_event.mouse_button.button_index==BUTTON_LEFT) {
|
||||
gui.drag_accum=Vector2();
|
||||
gui.drag_attempted=false;
|
||||
if (gui.drag_data.get_type()!=Variant::NIL) {
|
||||
_propagate_viewport_notification(this,NOTIFICATION_DRAG_END);
|
||||
}
|
||||
gui.drag_data=Variant();
|
||||
}
|
||||
|
||||
|
@ -1736,6 +1749,7 @@ void Viewport::_gui_input_event(InputEvent p_event) {
|
|||
|
||||
gui.mouse_over->drop_data(pos,gui.drag_data);
|
||||
gui.drag_data=Variant();
|
||||
_propagate_viewport_notification(this,NOTIFICATION_DRAG_END);
|
||||
//change mouse accordingly
|
||||
}
|
||||
|
||||
|
@ -1759,6 +1773,7 @@ void Viewport::_gui_input_event(InputEvent p_event) {
|
|||
}
|
||||
|
||||
if (gui.drag_data.get_type()!=Variant::NIL && p_event.mouse_button.button_index==BUTTON_LEFT) {
|
||||
_propagate_viewport_notification(this,NOTIFICATION_DRAG_END);
|
||||
gui.drag_data=Variant(); //always clear
|
||||
}
|
||||
|
||||
|
@ -1790,6 +1805,10 @@ void Viewport::_gui_input_event(InputEvent p_event) {
|
|||
gui.mouse_focus=NULL;
|
||||
}
|
||||
gui.drag_attempted=true;
|
||||
if (gui.drag_data.get_type()!=Variant::NIL) {
|
||||
|
||||
_propagate_viewport_notification(this,NOTIFICATION_DRAG_BEGIN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1814,6 +1833,8 @@ void Viewport::_gui_input_event(InputEvent p_event) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (over!=gui.mouse_over) {
|
||||
|
||||
if (gui.mouse_over)
|
||||
|
@ -1896,7 +1917,15 @@ void Viewport::_gui_input_event(InputEvent p_event) {
|
|||
|
||||
if (gui.drag_data.get_type()!=Variant::NIL && p_event.mouse_motion.button_mask&BUTTON_MASK_LEFT) {
|
||||
|
||||
/*bool can_drop =*/ over->can_drop_data(pos,gui.drag_data);
|
||||
|
||||
bool can_drop = over->can_drop_data(pos,gui.drag_data);
|
||||
|
||||
if (!can_drop) {
|
||||
OS::get_singleton()->set_cursor_shape( OS::CURSOR_FORBIDDEN );
|
||||
} else {
|
||||
OS::get_singleton()->set_cursor_shape( OS::CURSOR_CAN_DROP );
|
||||
|
||||
}
|
||||
//change mouse accordingly i guess
|
||||
}
|
||||
|
||||
|
@ -2367,6 +2396,9 @@ bool Viewport::is_input_disabled() const {
|
|||
return disable_input;
|
||||
}
|
||||
|
||||
Variant Viewport::gui_get_drag_data() const {
|
||||
return gui.drag_data;
|
||||
}
|
||||
void Viewport::_bind_methods() {
|
||||
|
||||
|
||||
|
@ -2452,6 +2484,7 @@ void Viewport::_bind_methods() {
|
|||
ObjectTypeDB::bind_method(_MD("warp_mouse","to_pos"), &Viewport::warp_mouse);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("gui_has_modal_stack"), &Viewport::gui_has_modal_stack);
|
||||
ObjectTypeDB::bind_method(_MD("gui_get_drag_data:Variant"), &Viewport::gui_get_drag_data);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_disable_input","disable"), &Viewport::set_disable_input);
|
||||
ObjectTypeDB::bind_method(_MD("is_input_disabled"), &Viewport::is_input_disabled);
|
||||
|
|
|
@ -159,6 +159,7 @@ friend class RenderTargetTexture;
|
|||
|
||||
void _propagate_enter_world(Node *p_node);
|
||||
void _propagate_exit_world(Node *p_node);
|
||||
void _propagate_viewport_notification(Node *p_node, int p_what);
|
||||
|
||||
|
||||
void _update_stretch_transform();
|
||||
|
@ -361,6 +362,7 @@ public:
|
|||
|
||||
bool gui_has_modal_stack() const;
|
||||
|
||||
Variant gui_get_drag_data() const;
|
||||
|
||||
Viewport();
|
||||
~Viewport();
|
||||
|
|
|
@ -655,6 +655,7 @@ void make_default_theme() {
|
|||
t->set_color("selection_color","Tree", Color(0.1,0.1,1,0.8) );
|
||||
t->set_color("cursor_color","Tree", Color(0,0,0) );
|
||||
t->set_color("guide_color","Tree", Color(0,0,0,0.1) );
|
||||
t->set_color("drop_position_color","Tree", Color(1,0.3,0.2) );
|
||||
|
||||
t->set_constant("hseparation","Tree",4);
|
||||
t->set_constant("vseparation","Tree",4);
|
||||
|
|
|
@ -523,7 +523,7 @@ void EditorNode::save_resource(const Ref<Resource>& p_resource) {
|
|||
}
|
||||
}
|
||||
|
||||
void EditorNode::save_resource_as(const Ref<Resource>& p_resource) {
|
||||
void EditorNode::save_resource_as(const Ref<Resource>& p_resource,const String& p_at_path) {
|
||||
|
||||
file->set_mode(EditorFileDialog::MODE_SAVE_FILE);
|
||||
bool relpaths = (p_resource->has_meta("__editor_relpaths__") && p_resource->get_meta("__editor_relpaths__").operator bool());
|
||||
|
@ -546,7 +546,21 @@ void EditorNode::save_resource_as(const Ref<Resource>& p_resource) {
|
|||
}
|
||||
|
||||
//file->set_current_path(current_path);
|
||||
if (p_resource->get_path()!="") {
|
||||
|
||||
if (p_at_path!=String()) {
|
||||
|
||||
file->set_current_dir(p_at_path);
|
||||
if (p_resource->get_path().is_resource_file()) {
|
||||
file->set_current_file(p_resource->get_path().get_file());
|
||||
} else {
|
||||
if (extensions.size()) {
|
||||
file->set_current_file("new_"+p_resource->get_type().to_lower()+"."+preferred.front()->get().to_lower());
|
||||
} else {
|
||||
file->set_current_file(String());
|
||||
}
|
||||
}
|
||||
} else if (p_resource->get_path()!="") {
|
||||
|
||||
file->set_current_path(p_resource->get_path());
|
||||
if (extensions.size()) {
|
||||
String ext=p_resource->get_path().extension().to_lower();
|
||||
|
@ -4881,6 +4895,114 @@ void EditorNode::remove_control_from_dock(Control* p_control) {
|
|||
_update_dock_slots_visibility();
|
||||
}
|
||||
|
||||
Variant EditorNode::drag_resource(const Ref<Resource>& p_res,Control* p_from) {
|
||||
|
||||
|
||||
Control *drag_control = memnew( Control );
|
||||
TextureFrame *drag_preview = memnew( TextureFrame );
|
||||
Label* label=memnew( Label );
|
||||
|
||||
Ref<Texture> preview;
|
||||
|
||||
{
|
||||
//todo make proper previews
|
||||
Ref<ImageTexture> pic = gui_base->get_icon("FileBig","EditorIcons");
|
||||
Image img = pic->get_data();
|
||||
img.resize(48,48); //meh
|
||||
Ref<ImageTexture> resized_pic = Ref<ImageTexture>( memnew( ImageTexture) );
|
||||
resized_pic->create_from_image(img);
|
||||
preview=resized_pic;
|
||||
}
|
||||
|
||||
drag_preview->set_texture(preview);
|
||||
drag_control->add_child(drag_preview);
|
||||
if (p_res->get_path().is_resource_file()) {
|
||||
label->set_text(p_res->get_path().get_file());
|
||||
} else if (p_res->get_name()!="") {
|
||||
label->set_text(p_res->get_name());
|
||||
} else {
|
||||
label->set_text(p_res->get_type());
|
||||
|
||||
}
|
||||
|
||||
drag_control->add_child(label);
|
||||
|
||||
p_from->set_drag_preview(drag_control); //wait until it enters scene
|
||||
|
||||
label->set_pos( Point2((preview->get_width()-label->get_minimum_size().width)/2,preview->get_height()) );
|
||||
|
||||
Dictionary drag_data;
|
||||
drag_data["type"]="resource";
|
||||
drag_data["resource"]=p_res;
|
||||
drag_data["from"]=p_from;
|
||||
|
||||
|
||||
return drag_data;
|
||||
|
||||
}
|
||||
|
||||
Variant EditorNode::drag_files(const Vector<String>& p_files, Control *p_from){
|
||||
|
||||
VBoxContainer *files = memnew( VBoxContainer );
|
||||
|
||||
int max_files=6;
|
||||
|
||||
for(int i=0;i<MIN(max_files,p_files.size());i++) {
|
||||
|
||||
Label* label=memnew( Label );
|
||||
label->set_text(p_files[i].get_file());
|
||||
files->add_child(label);
|
||||
}
|
||||
|
||||
if (p_files.size()>max_files) {
|
||||
|
||||
Label* label=memnew( Label );
|
||||
label->set_text(itos(p_files.size()-max_files)+" "+TTR("More File(s)"));
|
||||
files->add_child(label);
|
||||
|
||||
}
|
||||
Dictionary drag_data;
|
||||
drag_data["type"]="files";
|
||||
drag_data["files"]=p_files;
|
||||
drag_data["from"]=p_from;
|
||||
|
||||
p_from->set_drag_preview(files); //wait until it enters scene
|
||||
|
||||
return drag_data;
|
||||
|
||||
}
|
||||
|
||||
Variant EditorNode::drag_files_and_dirs(const Vector<String>& p_files, Control *p_from){
|
||||
|
||||
VBoxContainer *files = memnew( VBoxContainer );
|
||||
|
||||
int max_files=6;
|
||||
|
||||
for(int i=0;i<MIN(max_files,p_files.size());i++) {
|
||||
|
||||
Label* label=memnew( Label );
|
||||
label->set_text(p_files[i].get_file());
|
||||
files->add_child(label);
|
||||
}
|
||||
|
||||
if (p_files.size()>max_files) {
|
||||
|
||||
Label* label=memnew( Label );
|
||||
label->set_text(itos(p_files.size()-max_files)+" "+TTR("More File(s) and/or Directory(s)"));
|
||||
files->add_child(label);
|
||||
|
||||
}
|
||||
Dictionary drag_data;
|
||||
drag_data["type"]="files_and_dirs";
|
||||
drag_data["files"]=p_files;
|
||||
drag_data["from"]=p_from;
|
||||
|
||||
p_from->set_drag_preview(files); //wait until it enters scene
|
||||
|
||||
return drag_data;
|
||||
|
||||
}
|
||||
|
||||
void EditorNode::_bind_methods() {
|
||||
|
||||
|
||||
|
|
|
@ -584,6 +584,9 @@ public:
|
|||
static void add_editor_plugin(EditorPlugin *p_editor);
|
||||
static void remove_editor_plugin(EditorPlugin *p_editor);
|
||||
|
||||
|
||||
|
||||
|
||||
void add_control_to_dock(DockSlot p_slot,Control* p_control);
|
||||
void remove_control_from_dock(Control* p_control);
|
||||
|
||||
|
@ -599,7 +602,7 @@ public:
|
|||
|
||||
void save_resource_in_path(const Ref<Resource>& p_resource,const String& p_path);
|
||||
void save_resource(const Ref<Resource>& p_resource);
|
||||
void save_resource_as(const Ref<Resource>& p_resource);
|
||||
void save_resource_as(const Ref<Resource>& p_resource, const String &p_at_path=String());
|
||||
|
||||
static bool has_unsaved_changes() { return singleton->unsaved_cache; }
|
||||
|
||||
|
@ -696,6 +699,11 @@ public:
|
|||
void hide_bottom_panel();
|
||||
void remove_bottom_panel_item(Control *p_item);
|
||||
|
||||
Variant drag_resource(const Ref<Resource>& p_res,Control* p_from);
|
||||
Variant drag_files(const Vector<String>& p_files,Control* p_from);
|
||||
Variant drag_files_and_dirs(const Vector<String>& p_files,Control* p_from);
|
||||
|
||||
|
||||
EditorNode();
|
||||
~EditorNode();
|
||||
void get_singleton(const char* arg1, bool arg2);
|
||||
|
|
|
@ -572,6 +572,8 @@ bool CanvasItemEditor::_select(CanvasItem *item, Point2 p_click_pos, bool p_appe
|
|||
_append_canvas_item(item);
|
||||
viewport->update();
|
||||
|
||||
return true;
|
||||
|
||||
} else {
|
||||
//regular selection
|
||||
|
||||
|
|
|
@ -43,7 +43,8 @@
|
|||
#include "array_property_edit.h"
|
||||
#include "editor_help.h"
|
||||
#include "scene/resources/packed_scene.h"
|
||||
|
||||
#include "scene/main/viewport.h"
|
||||
#include "editor_file_system.h"
|
||||
|
||||
void CustomPropertyEditor::_notification(int p_what) {
|
||||
|
||||
|
@ -224,6 +225,10 @@ void CustomPropertyEditor::_menu_option(int p_which) {
|
|||
|
||||
}
|
||||
|
||||
void CustomPropertyEditor::hide_menu() {
|
||||
menu->hide();
|
||||
}
|
||||
|
||||
Variant CustomPropertyEditor::get_variant() const {
|
||||
|
||||
return v;
|
||||
|
@ -2257,6 +2262,179 @@ void PropertyEditor::_check_reload_status(const String&p_name, TreeItem* item) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool PropertyEditor::_is_drop_valid(const Dictionary& p_drag_data, const Dictionary& p_item_data) const {
|
||||
|
||||
Dictionary d = p_item_data;
|
||||
|
||||
if (d.has("type")) {
|
||||
|
||||
int type = d["type"];
|
||||
if (type==Variant::OBJECT && d.has("hint") && d.has("hint_text") && int(d["hint"])==PROPERTY_HINT_RESOURCE_TYPE) {
|
||||
|
||||
|
||||
String allowed_type=d["hint_text"];
|
||||
|
||||
Dictionary drag_data = p_drag_data;
|
||||
if (drag_data.has("type") && String(drag_data["type"])=="resource") {
|
||||
Ref<Resource> res = drag_data["resource"];
|
||||
for(int i=0;i<allowed_type.get_slice_count(",");i++) {
|
||||
String at = allowed_type.get_slice(",",i).strip_edges();
|
||||
if (res.is_valid() && ObjectTypeDB::is_type(res->get_type(),at)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (drag_data.has("type") && String(drag_data["type"])=="files") {
|
||||
|
||||
Vector<String> files = drag_data["files"];
|
||||
|
||||
if (files.size()==1) {
|
||||
String file = files[0];
|
||||
String ftype = EditorFileSystem::get_singleton()->get_file_type(file);
|
||||
if (ftype!="") {
|
||||
|
||||
for(int i=0;i<allowed_type.get_slice_count(",");i++) {
|
||||
String at = allowed_type.get_slice(",",i).strip_edges();
|
||||
if (ObjectTypeDB::is_type(ftype,at)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
void PropertyEditor::_mark_drop_fields(TreeItem* p_at) {
|
||||
|
||||
if (_is_drop_valid(get_viewport()->gui_get_drag_data(),p_at->get_metadata(0)))
|
||||
p_at->set_custom_bg_color(1,Color(0.7,0.5,0.2),true);
|
||||
|
||||
if (p_at->get_children()) {
|
||||
_mark_drop_fields(p_at->get_children());
|
||||
}
|
||||
|
||||
if (p_at->get_next()) {
|
||||
_mark_drop_fields(p_at->get_next());
|
||||
}
|
||||
}
|
||||
|
||||
Variant PropertyEditor::get_drag_data_fw(const Point2& p_point,Control* p_from) {
|
||||
|
||||
TreeItem *item = tree->get_item_at_pos(p_point);
|
||||
if (!item)
|
||||
return Variant();
|
||||
|
||||
int col = tree->get_column_at_pos(p_point);
|
||||
if (col!=1)
|
||||
return Variant();
|
||||
|
||||
|
||||
Dictionary d = item->get_metadata(0);
|
||||
if (!d.has("name"))
|
||||
return Variant();
|
||||
|
||||
Variant val = obj->get(d["name"]);
|
||||
|
||||
if (val.get_type()==Variant::OBJECT) {
|
||||
RES res = val;
|
||||
if (res.is_valid()) {
|
||||
|
||||
custom_editor->hide_menu();
|
||||
return EditorNode::get_singleton()->drag_resource(res,p_from);
|
||||
}
|
||||
}
|
||||
|
||||
return Variant();
|
||||
}
|
||||
|
||||
bool PropertyEditor::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const{
|
||||
|
||||
TreeItem *item = tree->get_item_at_pos(p_point);
|
||||
if (!item)
|
||||
return false;
|
||||
|
||||
int col = tree->get_column_at_pos(p_point);
|
||||
if (col!=1)
|
||||
return false;
|
||||
|
||||
return _is_drop_valid(p_data,item->get_metadata(0));
|
||||
|
||||
}
|
||||
void PropertyEditor::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from){
|
||||
|
||||
TreeItem *item = tree->get_item_at_pos(p_point);
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
int col = tree->get_column_at_pos(p_point);
|
||||
if (col!=1)
|
||||
return;
|
||||
|
||||
if (!_is_drop_valid(p_data,item->get_metadata(0)))
|
||||
return;
|
||||
|
||||
Dictionary d = item->get_metadata(0);
|
||||
|
||||
if (!d.has("name"))
|
||||
return;
|
||||
|
||||
String name=d["name"];
|
||||
|
||||
Dictionary drag_data = p_data;
|
||||
if (drag_data.has("type") && String(drag_data["type"])=="resource") {
|
||||
Ref<Resource> res = drag_data["resource"];
|
||||
if (res.is_valid()) {
|
||||
_edit_set(name,res);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (drag_data.has("type") && String(drag_data["type"])=="files") {
|
||||
|
||||
Vector<String> files = drag_data["files"];
|
||||
|
||||
if (files.size()==1) {
|
||||
String file = files[0];
|
||||
RES res = ResourceLoader::load(file);
|
||||
if (res.is_valid()) {
|
||||
_edit_set(name,res);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PropertyEditor::_clear_drop_fields(TreeItem* p_at) {
|
||||
|
||||
Dictionary d = p_at->get_metadata(0);
|
||||
|
||||
if (d.has("type")) {
|
||||
|
||||
int type = d["type"];
|
||||
if (type==Variant::OBJECT) {
|
||||
p_at->clear_custom_bg_color(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (p_at->get_children()) {
|
||||
_clear_drop_fields(p_at->get_children());
|
||||
}
|
||||
|
||||
if (p_at->get_next()) {
|
||||
_clear_drop_fields(p_at->get_next());
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyEditor::_notification(int p_what) {
|
||||
|
||||
if (p_what==NOTIFICATION_ENTER_TREE) {
|
||||
|
@ -2270,6 +2448,20 @@ void PropertyEditor::_notification(int p_what) {
|
|||
}
|
||||
|
||||
|
||||
if (p_what==NOTIFICATION_DRAG_BEGIN) {
|
||||
|
||||
if (is_visible() && tree->get_root()) {
|
||||
_mark_drop_fields(tree->get_root());
|
||||
}
|
||||
}
|
||||
|
||||
if (p_what==NOTIFICATION_DRAG_END) {
|
||||
if (is_visible() && tree->get_root()) {
|
||||
_clear_drop_fields(tree->get_root());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (p_what==NOTIFICATION_FIXED_PROCESS) {
|
||||
|
||||
|
||||
|
@ -3661,6 +3853,10 @@ void PropertyEditor::_bind_methods() {
|
|||
ObjectTypeDB::bind_method( "_filter_changed",&PropertyEditor::_filter_changed);
|
||||
ObjectTypeDB::bind_method( "update_tree",&PropertyEditor::update_tree);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("get_drag_data_fw"), &PropertyEditor::get_drag_data_fw);
|
||||
ObjectTypeDB::bind_method(_MD("can_drop_data_fw"), &PropertyEditor::can_drop_data_fw);
|
||||
ObjectTypeDB::bind_method(_MD("drop_data_fw"), &PropertyEditor::drop_data_fw);
|
||||
|
||||
ADD_SIGNAL( MethodInfo("property_toggled",PropertyInfo( Variant::STRING, "property"),PropertyInfo( Variant::BOOL, "value")));
|
||||
ADD_SIGNAL( MethodInfo("resource_selected", PropertyInfo( Variant::OBJECT, "res"),PropertyInfo( Variant::STRING, "prop") ) );
|
||||
ADD_SIGNAL( MethodInfo("property_keyed",PropertyInfo( Variant::STRING, "property")));
|
||||
|
@ -3778,6 +3974,8 @@ PropertyEditor::PropertyEditor() {
|
|||
tree->connect("item_edited", this,"_item_edited",varray(),CONNECT_DEFERRED);
|
||||
tree->connect("cell_selected", this,"_item_selected");
|
||||
|
||||
tree->set_drag_forwarding(this);
|
||||
|
||||
set_fixed_process(true);
|
||||
|
||||
custom_editor = memnew( CustomPropertyEditor );
|
||||
|
|
|
@ -137,6 +137,10 @@ protected:
|
|||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
|
||||
void hide_menu();
|
||||
|
||||
Variant get_variant() const;
|
||||
String get_name() const;
|
||||
|
||||
|
@ -219,6 +223,15 @@ class PropertyEditor : public Control {
|
|||
|
||||
void _filter_changed(const String& p_text);
|
||||
|
||||
void _mark_drop_fields(TreeItem* p_at);
|
||||
void _clear_drop_fields(TreeItem* p_at);
|
||||
|
||||
bool _is_drop_valid(const Dictionary& p_drag_data, const Dictionary& p_item_data) const;
|
||||
Variant get_drag_data_fw(const Point2& p_point,Control* p_from);
|
||||
bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const;
|
||||
void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
|
||||
|
||||
|
||||
UndoRedo *undo_redo;
|
||||
protected:
|
||||
|
||||
|
|
|
@ -40,6 +40,9 @@
|
|||
#include "tools/editor/plugins/animation_player_editor_plugin.h"
|
||||
#include "animation_editor.h"
|
||||
|
||||
|
||||
|
||||
|
||||
void SceneTreeDock::_unhandled_key_input(InputEvent p_event) {
|
||||
|
||||
uint32_t sc = p_event.key.get_scancode_with_modifiers();
|
||||
|
@ -943,16 +946,37 @@ bool SceneTreeDock::_validate_no_foreign() {
|
|||
void SceneTreeDock::_node_reparent(NodePath p_path,bool p_keep_global_xform) {
|
||||
|
||||
|
||||
Node *node = scene_tree->get_selected();
|
||||
ERR_FAIL_COND(!node);
|
||||
ERR_FAIL_COND(node==edited_scene);
|
||||
Node *new_parent = scene_root->get_node(p_path);
|
||||
ERR_FAIL_COND(!new_parent);
|
||||
|
||||
//ok all valid
|
||||
|
||||
List<Node*> selection = editor_selection->get_selected_node_list();
|
||||
|
||||
if (selection.empty())
|
||||
return; //nothing to reparent
|
||||
|
||||
Vector<Node*> nodes;
|
||||
|
||||
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
|
||||
nodes.push_back(E->get());
|
||||
}
|
||||
|
||||
_do_reparent(new_parent,-1,nodes,p_keep_global_xform);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void SceneTreeDock::_do_reparent(Node* p_new_parent,int p_position_in_parent,Vector<Node*> p_nodes,bool p_keep_global_xform) {
|
||||
|
||||
|
||||
Node *new_parent = p_new_parent;
|
||||
ERR_FAIL_COND(!new_parent);
|
||||
|
||||
Node *validate=new_parent;
|
||||
while(validate) {
|
||||
|
||||
if (editor_selection->is_selected(validate)) {
|
||||
if (p_nodes.find(validate)!=-1) {
|
||||
ERR_EXPLAIN("Selection changed at some point.. can't reparent");
|
||||
ERR_FAIL();
|
||||
return;
|
||||
|
@ -964,20 +988,20 @@ void SceneTreeDock::_node_reparent(NodePath p_path,bool p_keep_global_xform) {
|
|||
|
||||
List<Node*> selection = editor_selection->get_selected_node_list();
|
||||
|
||||
if (selection.empty())
|
||||
if (p_nodes.size()==0)
|
||||
return; //nothing to reparent
|
||||
|
||||
//sort by tree order, so re-adding is easy
|
||||
selection.sort_custom<Node::Comparator>();
|
||||
p_nodes.sort_custom<Node::Comparator>();
|
||||
|
||||
editor_data->get_undo_redo().create_action(TTR("Reparent Node"));
|
||||
|
||||
List<Pair<NodePath,NodePath> > path_renames;
|
||||
|
||||
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
|
||||
for(int ni=0;ni<p_nodes.size();ni++) {
|
||||
|
||||
//no undo for now, sorry
|
||||
Node *node = E->get();
|
||||
Node *node = p_nodes[ni];
|
||||
|
||||
fill_path_renames(node,new_parent,&path_renames);
|
||||
|
||||
|
@ -994,6 +1018,9 @@ void SceneTreeDock::_node_reparent(NodePath p_path,bool p_keep_global_xform) {
|
|||
editor_data->get_undo_redo().add_do_method(node->get_parent(),"remove_child",node);
|
||||
editor_data->get_undo_redo().add_do_method(new_parent,"add_child",node);
|
||||
|
||||
if (p_position_in_parent>=0)
|
||||
editor_data->get_undo_redo().add_do_method(new_parent,"move_child",node,p_position_in_parent+ni);
|
||||
|
||||
ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
|
||||
String new_name = new_parent->validate_child_name(node->get_name());
|
||||
editor_data->get_undo_redo().add_do_method(sed,"live_debug_reparent_node",edited_scene->get_path_to(node),edited_scene->get_path_to(new_parent),new_name,-1);
|
||||
|
@ -1030,9 +1057,9 @@ void SceneTreeDock::_node_reparent(NodePath p_path,bool p_keep_global_xform) {
|
|||
|
||||
|
||||
|
||||
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
|
||||
for(int ni=0;ni<p_nodes.size();ni++) {
|
||||
|
||||
Node *node = E->get();
|
||||
Node *node = p_nodes[ni];
|
||||
|
||||
List<Node*> owned;
|
||||
node->get_owned_by(node->get_owner(),&owned);
|
||||
|
@ -1078,7 +1105,6 @@ void SceneTreeDock::_node_reparent(NodePath p_path,bool p_keep_global_xform) {
|
|||
//node->set_owner(owner);
|
||||
}
|
||||
|
||||
|
||||
void SceneTreeDock::_script_created(Ref<Script> p_script) {
|
||||
|
||||
Node *selected = scene_tree->get_selected();
|
||||
|
@ -1431,6 +1457,161 @@ void SceneTreeDock::_new_scene_from(String p_file) {
|
|||
|
||||
}
|
||||
|
||||
static bool _is_node_visible(Node* p_node) {
|
||||
|
||||
if (!p_node->get_owner())
|
||||
return false;
|
||||
if (p_node->get_owner()!=EditorNode::get_singleton()->get_edited_scene() && !EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node->get_owner()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
static bool _has_visible_children(Node* p_node) {
|
||||
|
||||
bool collapsed = p_node->has_meta("_editor_collapsed") ? (bool)p_node->get_meta("_editor_collapsed") : false;
|
||||
if (collapsed)
|
||||
return false;
|
||||
|
||||
for(int i=0;i<p_node->get_child_count();i++) {
|
||||
|
||||
Node* child = p_node->get_child(i);
|
||||
if (!_is_node_visible(p_node))
|
||||
continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static Node* _find_last_visible(Node*p_node) {
|
||||
|
||||
Node*last=NULL;
|
||||
for(int i=0;i<p_node->get_child_count();i++) {
|
||||
if (_is_node_visible(p_node->get_child(i))) {
|
||||
last=p_node->get_child(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (last) {
|
||||
Node* lastc=_find_last_visible(last);
|
||||
if (lastc)
|
||||
last=lastc;
|
||||
|
||||
|
||||
} else {
|
||||
last=p_node;
|
||||
}
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
void SceneTreeDock::_nodes_dragged(Array p_nodes,NodePath p_to,int p_type) {
|
||||
|
||||
Vector<Node*> nodes;
|
||||
Node *to_node;
|
||||
|
||||
for(int i=0;i<p_nodes.size();i++) {
|
||||
Node *n=get_node((p_nodes[i]));
|
||||
nodes.push_back(n);
|
||||
}
|
||||
|
||||
if (nodes.size()==0)
|
||||
return;
|
||||
|
||||
to_node=get_node(p_to);
|
||||
if (!to_node)
|
||||
return;
|
||||
|
||||
|
||||
int to_pos=-1;
|
||||
|
||||
if (p_type==1 && to_node==EditorNode::get_singleton()->get_edited_scene()) {
|
||||
//if at lower sibling of root node
|
||||
to_pos=0; //just insert at begining of root node
|
||||
} else if (p_type==-1) {
|
||||
//drop at above selected node
|
||||
ERR_FAIL_COND(to_node==EditorNode::get_singleton()->get_edited_scene());
|
||||
Node* upper_sibling=NULL;
|
||||
|
||||
for(int i=0;i<to_node->get_index();i++) {
|
||||
Node *c =to_node->get_parent()->get_child(i);
|
||||
if (_is_node_visible(c)) {
|
||||
upper_sibling=c;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (upper_sibling) {
|
||||
//quite complicated, look for next visible in tree
|
||||
upper_sibling=_find_last_visible(upper_sibling);
|
||||
|
||||
if (upper_sibling->get_parent()==to_node->get_parent()) {
|
||||
//just insert over this node because nothing is above at an upper level
|
||||
to_pos=to_node->get_index();
|
||||
to_node=to_node->get_parent();
|
||||
} else {
|
||||
to_pos=-1; //insert last in whathever is up
|
||||
to_node=upper_sibling->get_parent(); //insert at a parent of whathever is up
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
//just insert over this node because nothing is above at the same level
|
||||
to_pos=to_node->get_index();
|
||||
to_node=to_node->get_parent();
|
||||
}
|
||||
|
||||
} else if (p_type==1) {
|
||||
//drop at below selected node
|
||||
ERR_FAIL_COND(to_node==EditorNode::get_singleton()->get_edited_scene());
|
||||
|
||||
|
||||
Node* lower_sibling=NULL;
|
||||
|
||||
for(int i=to_node->get_index()+1;i<to_node->get_parent()->get_child_count();i++) {
|
||||
Node *c =to_node->get_parent()->get_child(i);
|
||||
if (_is_node_visible(c)) {
|
||||
lower_sibling=c;
|
||||
}
|
||||
}
|
||||
|
||||
if (lower_sibling) {
|
||||
to_pos=lower_sibling->get_index();
|
||||
}
|
||||
|
||||
to_node=to_node->get_parent();
|
||||
#if 0
|
||||
//quite complicated, look for next visible in tree
|
||||
upper_sibling=_find_last_visible(upper_sibling);
|
||||
|
||||
if (upper_sibling->get_parent()==to_node->get_parent()) {
|
||||
//just insert over this node because nothing is above at an upper level
|
||||
to_pos=to_node->get_index();
|
||||
to_node=to_node->get_parent();
|
||||
} else {
|
||||
to_pos=-1; //insert last in whathever is up
|
||||
to_node=upper_sibling->get_parent(); //insert at a parent of whathever is up
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
//just insert over this node because nothing is above at the same level
|
||||
to_pos=to_node->get_index();
|
||||
to_node=to_node->get_parent();
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
_do_reparent(to_node,to_pos,nodes,true);
|
||||
|
||||
}
|
||||
|
||||
void SceneTreeDock::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_tool_selected"),&SceneTreeDock::_tool_selected);
|
||||
|
@ -1449,6 +1630,8 @@ void SceneTreeDock::_bind_methods() {
|
|||
ObjectTypeDB::bind_method(_MD("_import_subscene"),&SceneTreeDock::_import_subscene);
|
||||
ObjectTypeDB::bind_method(_MD("_selection_changed"),&SceneTreeDock::_selection_changed);
|
||||
ObjectTypeDB::bind_method(_MD("_new_scene_from"),&SceneTreeDock::_new_scene_from);
|
||||
ObjectTypeDB::bind_method(_MD("_nodes_dragged"),&SceneTreeDock::_nodes_dragged);
|
||||
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("instance"),&SceneTreeDock::instance);
|
||||
}
|
||||
|
@ -1518,6 +1701,8 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelec
|
|||
scene_tree->connect("node_prerename", this,"_node_prerenamed");
|
||||
scene_tree->connect("open",this,"_load_request");
|
||||
scene_tree->connect("open_script",this,"_script_open_request");
|
||||
scene_tree->connect("nodes_rearranged",this,"_nodes_dragged");
|
||||
|
||||
scene_tree->set_undo_redo(&editor_data->get_undo_redo());
|
||||
scene_tree->set_editor_selection(editor_selection);
|
||||
|
||||
|
@ -1612,6 +1797,8 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelec
|
|||
add_child(new_scene_from_dialog);
|
||||
new_scene_from_dialog->connect("file_selected",this,"_new_scene_from");
|
||||
|
||||
|
||||
|
||||
first_enter=true;
|
||||
|
||||
|
||||
|
|
|
@ -102,6 +102,8 @@ class SceneTreeDock : public VBoxContainer {
|
|||
|
||||
Node *_duplicate(Node *p_node, Map<Node*,Node*> &duplimap);
|
||||
void _node_reparent(NodePath p_path, bool p_keep_global_xform);
|
||||
void _do_reparent(Node* p_new_parent, int p_position_in_parent, Vector<Node*> p_nodes, bool p_keep_global_xform);
|
||||
|
||||
void _set_owners(Node *p_owner, const Array& p_nodes);
|
||||
void _load_request(const String& p_path);
|
||||
void _script_open_request(const Ref<Script>& p_script);
|
||||
|
@ -128,6 +130,8 @@ class SceneTreeDock : public VBoxContainer {
|
|||
|
||||
void _fill_path_renames(Vector<StringName> base_path,Vector<StringName> new_base_path,Node * p_node, List<Pair<NodePath,NodePath> > *p_renames);
|
||||
|
||||
void _nodes_dragged(Array p_nodes,NodePath p_to,int p_type);
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
|
|
|
@ -784,6 +784,96 @@ void SceneTreeEditor::_cell_collapsed(Object *p_obj) {
|
|||
|
||||
}
|
||||
|
||||
Variant SceneTreeEditor::get_drag_data_fw(const Point2& p_point,Control* p_from) {
|
||||
if (!can_rename)
|
||||
return Variant(); //not editable tree
|
||||
|
||||
Vector<Node*> selected;
|
||||
Vector<Ref<Texture> > icons;
|
||||
TreeItem *next=tree->get_next_selected(NULL);
|
||||
while (next) {
|
||||
|
||||
NodePath np = next->get_metadata(0);
|
||||
|
||||
Node *n=get_node(np);
|
||||
if (n) {
|
||||
|
||||
selected.push_back(n);
|
||||
icons.push_back(next->get_icon(0));
|
||||
}
|
||||
next=tree->get_next_selected(next);
|
||||
}
|
||||
|
||||
if (selected.empty())
|
||||
return Variant();
|
||||
|
||||
VBoxContainer *vb = memnew( VBoxContainer );
|
||||
Array objs;
|
||||
for(int i=0;i<selected.size();i++) {
|
||||
|
||||
HBoxContainer *hb = memnew( HBoxContainer );
|
||||
TextureFrame *tf = memnew(TextureFrame);
|
||||
tf->set_texture(icons[i]);
|
||||
hb->add_child(tf);
|
||||
Label *label = memnew( Label( selected[i]->get_name() ) );
|
||||
hb->add_child(label);
|
||||
vb->add_child(hb);
|
||||
NodePath p = selected[i]->get_path();
|
||||
objs.push_back(p);
|
||||
}
|
||||
|
||||
set_drag_preview(vb);
|
||||
Dictionary drag_data;
|
||||
drag_data["type"]="nodes";
|
||||
drag_data["nodes"]=objs;
|
||||
|
||||
tree->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN|Tree::DROP_MODE_ON_ITEM);
|
||||
|
||||
|
||||
return drag_data;
|
||||
}
|
||||
|
||||
bool SceneTreeEditor::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const {
|
||||
|
||||
if (!can_rename)
|
||||
return false; //not editable tree
|
||||
|
||||
Dictionary d=p_data;
|
||||
if (!d.has("type") || String(d["type"])!="nodes")
|
||||
return false;
|
||||
TreeItem *item = tree->get_item_at_pos(p_point);
|
||||
if (!item)
|
||||
return false;
|
||||
int section = tree->get_drop_section_at_pos(p_point);
|
||||
if (section<-1 || (section==-1 && !item->get_parent()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
void SceneTreeEditor::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) {
|
||||
|
||||
if (!can_drop_data_fw(p_point,p_data,p_from))
|
||||
return;
|
||||
|
||||
TreeItem *item = tree->get_item_at_pos(p_point);
|
||||
if (!item)
|
||||
return;
|
||||
int section = tree->get_drop_section_at_pos(p_point);
|
||||
if (section<-1)
|
||||
return;
|
||||
|
||||
NodePath np = item->get_metadata(0);
|
||||
Node *n=get_node(np);
|
||||
if (!n)
|
||||
return;
|
||||
|
||||
Dictionary d=p_data;
|
||||
|
||||
Array nodes=d["nodes"];
|
||||
|
||||
emit_signal("nodes_rearranged",nodes,np,section);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void SceneTreeEditor::_bind_methods() {
|
||||
|
@ -804,10 +894,15 @@ void SceneTreeEditor::_bind_methods() {
|
|||
ObjectTypeDB::bind_method("_node_script_changed",&SceneTreeEditor::_node_script_changed);
|
||||
ObjectTypeDB::bind_method("_node_visibility_changed",&SceneTreeEditor::_node_visibility_changed);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("get_drag_data_fw"), &SceneTreeEditor::get_drag_data_fw);
|
||||
ObjectTypeDB::bind_method(_MD("can_drop_data_fw"), &SceneTreeEditor::can_drop_data_fw);
|
||||
ObjectTypeDB::bind_method(_MD("drop_data_fw"), &SceneTreeEditor::drop_data_fw);
|
||||
|
||||
ADD_SIGNAL( MethodInfo("node_selected") );
|
||||
ADD_SIGNAL( MethodInfo("node_renamed") );
|
||||
ADD_SIGNAL( MethodInfo("node_prerename") );
|
||||
ADD_SIGNAL( MethodInfo("node_changed") );
|
||||
ADD_SIGNAL( MethodInfo("nodes_rearranged",PropertyInfo(Variant::ARRAY,"paths"),PropertyInfo(Variant::NODE_PATH,"to_path"),PropertyInfo(Variant::INT,"type") ) );
|
||||
|
||||
ADD_SIGNAL( MethodInfo("open") );
|
||||
ADD_SIGNAL( MethodInfo("open_script") );
|
||||
|
@ -846,6 +941,8 @@ SceneTreeEditor::SceneTreeEditor(bool p_label,bool p_can_rename, bool p_can_open
|
|||
|
||||
add_child( tree );
|
||||
|
||||
tree->set_drag_forwarding(this);
|
||||
|
||||
tree->connect("cell_selected", this,"_selected_changed");
|
||||
tree->connect("item_edited", this,"_renamed",varray(),CONNECT_DEFERRED);
|
||||
tree->connect("multi_selected",this,"_cell_multi_selected");
|
||||
|
|
|
@ -111,8 +111,14 @@ class SceneTreeEditor : public Control {
|
|||
void _node_visibility_changed(Node *p_node);
|
||||
void _subscene_option(int p_idx);
|
||||
|
||||
|
||||
void _selection_changed();
|
||||
Node *get_scene_node();
|
||||
|
||||
Variant get_drag_data_fw(const Point2& p_point,Control* p_from);
|
||||
bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const;
|
||||
void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
|
||||
|
||||
public:
|
||||
|
||||
|
||||
|
|
|
@ -451,7 +451,7 @@ void ScenesDock::_update_files(bool p_keep_selection) {
|
|||
img.resize(thumbnail_size,thumbnail_size);
|
||||
Ref<ImageTexture> resized_folder = Ref<ImageTexture>( memnew( ImageTexture));
|
||||
resized_folder->create_from_image(img,0);
|
||||
Theme::get_default()->set_icon(TTR("ResizedFolder"),"EditorIcons",resized_folder);
|
||||
Theme::get_default()->set_icon("ResizedFolder","EditorIcons",resized_folder);
|
||||
}
|
||||
|
||||
folder_thumbnail = get_icon("ResizedFolder","EditorIcons");
|
||||
|
@ -462,7 +462,7 @@ void ScenesDock::_update_files(bool p_keep_selection) {
|
|||
img.resize(thumbnail_size,thumbnail_size);
|
||||
Ref<ImageTexture> resized_file = Ref<ImageTexture>( memnew( ImageTexture));
|
||||
resized_file->create_from_image(img,0);
|
||||
Theme::get_default()->set_icon(TTR("ResizedFile"),"EditorIcons",resized_file);
|
||||
Theme::get_default()->set_icon("ResizedFile","EditorIcons",resized_file);
|
||||
}
|
||||
|
||||
file_thumbnail = get_icon("ResizedFile","EditorIcons");
|
||||
|
@ -1073,6 +1073,142 @@ void ScenesDock::set_use_thumbnails(bool p_use) {
|
|||
display_mode->set_pressed(!p_use);
|
||||
}
|
||||
|
||||
|
||||
Variant ScenesDock::get_drag_data_fw(const Point2& p_point,Control* p_from) {
|
||||
|
||||
if (p_from==files) {
|
||||
|
||||
List<int> seldirs;
|
||||
List<int> selfiles;
|
||||
|
||||
for (int i = 0; i<files->get_item_count(); i++) {
|
||||
if (files->is_selected(i)) {
|
||||
String path = files->get_item_metadata(i);
|
||||
if (path.ends_with("/"))
|
||||
seldirs.push_back(i);
|
||||
else
|
||||
selfiles.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (seldirs.empty() && selfiles.empty())
|
||||
return Variant();
|
||||
//if (seldirs.size() && selfiles.size())
|
||||
// return Variant(); //can't really mix files and dirs (i think?) - yes you can, commenting
|
||||
|
||||
/*if (selfiles.size()==1) {
|
||||
Ref<Resource> resource = ResourceLoader::load(files->get_item_metadata(selfiles.front()->get()));
|
||||
if (resource.is_valid()) {
|
||||
return EditorNode::get_singleton()->drag_resource(resource,p_from);
|
||||
}
|
||||
}*/
|
||||
|
||||
if (selfiles.size()>0 && seldirs.size()==0) {
|
||||
Vector<String> fnames;
|
||||
for(List<int>::Element *E=selfiles.front();E;E=E->next()) {
|
||||
fnames.push_back(files->get_item_metadata(E->get()));
|
||||
}
|
||||
return EditorNode::get_singleton()->drag_files(fnames,p_from);
|
||||
}
|
||||
|
||||
if (selfiles.size()>0 || seldirs.size()>0) {
|
||||
Vector<String> fnames;
|
||||
for(List<int>::Element *E=selfiles.front();E;E=E->next()) {
|
||||
fnames.push_back(files->get_item_metadata(E->get()));
|
||||
}
|
||||
for(List<int>::Element *E=seldirs.front();E;E=E->next()) {
|
||||
fnames.push_back(files->get_item_metadata(E->get()));
|
||||
}
|
||||
return EditorNode::get_singleton()->drag_files_and_dirs(fnames,p_from);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return Variant();
|
||||
}
|
||||
|
||||
bool ScenesDock::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const{
|
||||
|
||||
Dictionary drag_data = p_data;
|
||||
|
||||
print_line("CAN IT DROP DATA?");
|
||||
if (drag_data.has("type") && String(drag_data["type"])=="resource") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (drag_data.has("type") && ( String(drag_data["type"])=="files" || String(drag_data["type"])=="files_and_dirs")) {
|
||||
|
||||
Vector<String> fnames = drag_data["files"];
|
||||
|
||||
if (p_from==files) {
|
||||
|
||||
int at_pos = files->get_item_at_pos(p_point);
|
||||
if (at_pos!=-1) {
|
||||
|
||||
String dir = files->get_item_metadata(at_pos);
|
||||
if (dir.ends_with("/"))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ScenesDock::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from){
|
||||
|
||||
if (!can_drop_data_fw(p_point,p_data,p_from))
|
||||
return;
|
||||
Dictionary drag_data = p_data;
|
||||
|
||||
if (drag_data.has("type") && String(drag_data["type"])=="resource") {
|
||||
Ref<Resource> res = drag_data["resource"];
|
||||
|
||||
if (!res.is_valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String save_path=path;
|
||||
|
||||
int at_pos = files->get_item_at_pos(p_point);
|
||||
if (at_pos!=-1) {
|
||||
String to_dir = files->get_item_metadata(at_pos);
|
||||
if (to_dir.ends_with("/")) {
|
||||
save_path=to_dir;
|
||||
if (save_path!="res://")
|
||||
save_path=save_path.substr(0,save_path.length()-1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
EditorNode::get_singleton()->save_resource_as(res,save_path);
|
||||
return;
|
||||
}
|
||||
|
||||
if (drag_data.has("type") && ( String(drag_data["type"])=="files" || String(drag_data["type"])=="files_and_dirs")) {
|
||||
|
||||
int at_pos = files->get_item_at_pos(p_point);
|
||||
ERR_FAIL_COND(at_pos==-1);
|
||||
String to_dir = files->get_item_metadata(at_pos);
|
||||
ERR_FAIL_COND(!to_dir.ends_with("/"));
|
||||
|
||||
Vector<String> fnames = drag_data["files"];
|
||||
move_files.clear();
|
||||
move_dirs.clear();
|
||||
|
||||
for(int i=0;i<fnames.size();i++) {
|
||||
if (fnames[i].ends_with("/"))
|
||||
move_dirs.push_back(fnames[i]);
|
||||
else
|
||||
move_files.push_back(fnames[i]);
|
||||
}
|
||||
|
||||
_move_operation(to_dir);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ScenesDock::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_update_tree"),&ScenesDock::_update_tree);
|
||||
|
@ -1096,6 +1232,10 @@ void ScenesDock::_bind_methods() {
|
|||
ObjectTypeDB::bind_method(_MD("_move_operation"), &ScenesDock::_move_operation);
|
||||
ObjectTypeDB::bind_method(_MD("_rename_operation"), &ScenesDock::_rename_operation);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("get_drag_data_fw"), &ScenesDock::get_drag_data_fw);
|
||||
ObjectTypeDB::bind_method(_MD("can_drop_data_fw"), &ScenesDock::can_drop_data_fw);
|
||||
ObjectTypeDB::bind_method(_MD("drop_data_fw"), &ScenesDock::drop_data_fw);
|
||||
|
||||
ADD_SIGNAL(MethodInfo("instance"));
|
||||
ADD_SIGNAL(MethodInfo("open"));
|
||||
|
||||
|
@ -1199,6 +1339,7 @@ ScenesDock::ScenesDock(EditorNode *p_editor) {
|
|||
files = memnew( ItemList );
|
||||
files->set_v_size_flags(SIZE_EXPAND_FILL);
|
||||
files->set_select_mode(ItemList::SELECT_MULTI);
|
||||
files->set_drag_forwarding(this);
|
||||
|
||||
path_hb = memnew( HBoxContainer );
|
||||
button_back = memnew( ToolButton );
|
||||
|
|
|
@ -142,6 +142,9 @@ class ScenesDock : public VBoxContainer {
|
|||
void _instance_pressed();
|
||||
void _open_pressed();
|
||||
|
||||
Variant get_drag_data_fw(const Point2& p_point,Control* p_from);
|
||||
bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const;
|
||||
void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
|
|
Loading…
Reference in a new issue