diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/editor/editor_file_dialog.cpp | 47 | ||||
-rw-r--r-- | tools/editor/plugins/canvas_item_editor_plugin.cpp | 405 | ||||
-rw-r--r-- | tools/editor/plugins/canvas_item_editor_plugin.h | 52 | ||||
-rw-r--r-- | tools/editor/scene_tree_dock.cpp | 75 | ||||
-rw-r--r-- | tools/editor/scene_tree_dock.h | 9 | ||||
-rw-r--r-- | tools/editor/scene_tree_editor.cpp | 25 | ||||
-rw-r--r-- | tools/editor/scene_tree_editor.h | 3 |
7 files changed, 582 insertions, 34 deletions
diff --git a/tools/editor/editor_file_dialog.cpp b/tools/editor/editor_file_dialog.cpp index b8abd1d32c..90289a275e 100644 --- a/tools/editor/editor_file_dialog.cpp +++ b/tools/editor/editor_file_dialog.cpp @@ -336,15 +336,21 @@ void EditorFileDialog::_action_pressed() { hide(); }else if (mode==MODE_OPEN_ANY || mode==MODE_OPEN_DIR) { - String path=dir_access->get_current_dir(); - /*if (tree->get_selected()) { - Dictionary d = tree->get_selected()->get_metadata(0); - if (d["dir"]) { - path=path+"/"+String(d["name"]); - } - }*/ + path=path.replace("\\","/"); + + for(int i=0;i<item_list->get_item_count();i++) { + if (item_list->is_selected(i)) { + Dictionary d=item_list->get_item_metadata(i); + if (d["dir"]) { + path=path.plus_file(d["name"]); + + break; + } + } + } + _save_to_recent(); emit_signal("dir_selected",path); hide(); @@ -571,25 +577,26 @@ void EditorFileDialog::update_file_list() { files.sort_custom<NoCaseComparator>(); while(!dirs.empty()) { + const String& dir_name=dirs.front()->get(); - if (dirs.front()->get()!=".") { - item_list->add_item(dirs.front()->get()+"/"); - if (display_mode==DISPLAY_THUMBNAILS) { + item_list->add_item(dir_name+"/"); - item_list->set_item_icon(item_list->get_item_count()-1,folder_thumbnail); - } else { + if (display_mode==DISPLAY_THUMBNAILS) { - item_list->set_item_icon(item_list->get_item_count()-1,folder); - } + item_list->set_item_icon(item_list->get_item_count()-1,folder_thumbnail); + } else { - Dictionary d; - d["name"]=dirs.front()->get(); - d["path"]=String(); - d["dir"]=true; - item_list->set_item_metadata( item_list->get_item_count() -1, d); + item_list->set_item_icon(item_list->get_item_count()-1,folder); } - dirs.pop_front(); + Dictionary d; + d["name"]=dir_name; + d["path"]=String(); + d["dir"]=true; + + item_list->set_item_metadata( item_list->get_item_count() -1, d); + + dirs.pop_front(); } dirs.clear(); diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp index b0e002ba44..ac39e0687c 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.cpp +++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp @@ -32,13 +32,20 @@ #include "os/keyboard.h" #include "scene/main/viewport.h" #include "scene/main/canvas_layer.h" -#include "scene/2d/node_2d.h" +#include "scene/2d/sprite.h" +#include "scene/2d/light_2d.h" +#include "scene/2d/particles_2d.h" +#include "scene/2d/polygon_2d.h" +#include "scene/2d/screen_button.h" #include "globals.h" #include "os/input.h" #include "tools/editor/editor_settings.h" #include "scene/gui/grid_container.h" +#include "scene/gui/patch_9_frame.h" #include "tools/editor/animation_editor.h" #include "tools/editor/plugins/animation_player_editor_plugin.h" +#include "tools/editor/script_editor_debugger.h" +#include "tools/editor/plugins/script_editor_plugin.h" #include "scene/resources/packed_scene.h" @@ -3326,7 +3333,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { vp->add_child(p_editor->get_scene_root()); - viewport = memnew( Control ); + viewport = memnew( CanvasItemEditorViewport(p_editor, this) ); vp_base->add_child(viewport); viewport->set_area_as_parent_rect(); @@ -3642,3 +3649,397 @@ CanvasItemEditorPlugin::~CanvasItemEditorPlugin() } +void CanvasItemEditorViewport::_on_mouse_exit() { + if (selector->is_hidden()){ + _remove_preview(); + } +} + +void CanvasItemEditorViewport::_on_select_type(Object* selected) { + CheckBox* check = selected->cast_to<CheckBox>(); + String type = check->get_text(); + selector_label->set_text(vformat(TTR("Add %s"),type)); + label->set_text(vformat(TTR("Adding %s..."),type)); +} + +void CanvasItemEditorViewport::_on_change_type() { + CheckBox* check=btn_group->get_pressed_button()->cast_to<CheckBox>(); + default_type=check->get_text(); + _perform_drop_data(); + selector->hide(); +} + +void CanvasItemEditorViewport::_create_preview(const Vector<String>& files) const { + label->set_pos(get_global_pos()+Point2(14,14)); + label_desc->set_pos(label->get_pos()+Point2(0,label->get_size().height)); + for (int i=0;i<files.size();i++) { + String path=files[i]; + RES res=ResourceLoader::load(path); + String type=res->get_type(); + if (type=="ImageTexture" || type=="PackedScene") { + if (type=="ImageTexture") { + Ref<ImageTexture> texture=Ref<ImageTexture> ( ResourceCache::get(path)->cast_to<ImageTexture>() ); + Sprite* sprite=memnew(Sprite); + sprite->set_texture(texture); + sprite->set_opacity(0.7f); + preview->add_child(sprite); + label->show(); + label_desc->show(); + } else if (type=="PackedScene") { + Ref<PackedScene> scn=ResourceLoader::load(path); + if (scn.is_valid()){ + Node* instance=scn->instance(); + if (instance){ + preview->add_child(instance); + } + } + } + editor->get_scene_root()->add_child(preview); + } + } +} + +void CanvasItemEditorViewport::_remove_preview() { + if (preview->get_parent()){ + editor->get_scene_root()->remove_child(preview); + for (int i=preview->get_child_count()-1;i>=0;i--){ + Node* node=preview->get_child(i); + memdelete(node); + } + label->hide(); + label_desc->hide(); + } +} + +bool CanvasItemEditorViewport::_cyclical_dependency_exists(const String& p_target_scene_path, Node* p_desired_node) { + if (p_desired_node->get_filename()==p_target_scene_path) { + return true; + } + + int childCount=p_desired_node->get_child_count(); + for (int i=0;i<childCount;i++) { + Node* child=p_desired_node->get_child(i); + if(_cyclical_dependency_exists(p_target_scene_path,child)) { + return true; + } + } + return false; +} + +void CanvasItemEditorViewport::_create_nodes(Node* parent, Node* child, String& path, const Point2& p_point) { + child->set_name(path.get_file().basename()); + Ref<ImageTexture> texture=Ref<ImageTexture> ( ResourceCache::get(path)->cast_to<ImageTexture>() ); + Size2 texture_size = texture->get_size(); + + editor_data->get_undo_redo().add_do_method(parent,"add_child",child); + editor_data->get_undo_redo().add_do_method(child,"set_owner",editor->get_edited_scene()); + editor_data->get_undo_redo().add_do_reference(child); + editor_data->get_undo_redo().add_undo_method(parent,"remove_child",child); + + String new_name=parent->validate_child_name(child); + ScriptEditorDebugger *sed=ScriptEditor::get_singleton()->get_debugger(); + editor_data->get_undo_redo().add_do_method(sed,"live_debug_create_node",editor->get_edited_scene()->get_path_to(parent),child->get_type(),new_name); + editor_data->get_undo_redo().add_undo_method(sed,"live_debug_remove_node",NodePath(String(editor->get_edited_scene()->get_path_to(parent))+"/"+new_name)); + + // handle with different property for texture + String property = "texture"; + List<PropertyInfo> props; + child->get_property_list(&props); + for(const List<PropertyInfo>::Element *E=props.front();E;E=E->next() ) { + if (E->get().name=="config/texture") { // Particles2D + property="config/texture"; + break; + } else if (E->get().name=="texture/texture") { // Polygon2D + property="texture/texture"; + break; + } else if (E->get().name=="normal") { // TouchScreenButton + property="normal"; + break; + } + } + editor_data->get_undo_redo().add_do_property(child,property,texture); + + // make visible for certain node type + if (default_type=="Patch9Frame") { + editor_data->get_undo_redo().add_do_property(child,"rect/size",texture_size); + } else if (default_type=="Polygon2D") { + DVector<Vector2> list; + list.push_back(Vector2(0,0)); + list.push_back(Vector2(texture_size.width,0)); + list.push_back(Vector2(texture_size.width,texture_size.height)); + list.push_back(Vector2(0,texture_size.height)); + editor_data->get_undo_redo().add_do_property(child,"polygon",list); + } + + // locate at preview position + Point2 pos; + if (parent->has_method("get_global_pos")) { + pos=parent->call("get_global_pos"); + } + Matrix32 trans=canvas->get_canvas_transform(); + Point2 target_pos = (p_point-trans.get_origin())/trans.get_scale().x-pos; + if (default_type=="Polygon2D" || default_type=="TouchScreenButton" || default_type=="TextureFrame" || default_type=="Patch9Frame") { + target_pos -= texture_size/2; + } + editor_data->get_undo_redo().add_do_method(child,"set_pos",target_pos); +} + +bool CanvasItemEditorViewport::_create_instance(Node* parent, String& path, const Point2& p_point) { + Ref<PackedScene> sdata=ResourceLoader::load(path); + if (!sdata.is_valid()) { // invalid scene + return false; + } + + Node* instanced_scene=sdata->instance(true); + if (!instanced_scene) { // error on instancing + return false; + } + + if (editor->get_edited_scene()->get_filename()!="") { // cyclical instancing + if (_cyclical_dependency_exists(editor->get_edited_scene()->get_filename(), instanced_scene)) { + return false; + } + } + + instanced_scene->set_filename( Globals::get_singleton()->localize_path(path) ); + + editor_data->get_undo_redo().add_do_method(parent,"add_child",instanced_scene); + editor_data->get_undo_redo().add_do_method(instanced_scene,"set_owner",editor->get_edited_scene()); + editor_data->get_undo_redo().add_do_reference(instanced_scene); + editor_data->get_undo_redo().add_undo_method(parent,"remove_child",instanced_scene); + + String new_name=parent->validate_child_name(instanced_scene); + ScriptEditorDebugger *sed=ScriptEditor::get_singleton()->get_debugger(); + editor_data->get_undo_redo().add_do_method(sed,"live_debug_instance_node",editor->get_edited_scene()->get_path_to(parent),path,new_name); + editor_data->get_undo_redo().add_undo_method(sed,"live_debug_remove_node",NodePath(String(editor->get_edited_scene()->get_path_to(parent))+"/"+new_name)); + + Point2 pos; + Node2D* parent_node2d=parent->cast_to<Node2D>(); + if (parent_node2d) { + pos=parent_node2d->get_global_pos(); + } else { + Control* parent_control=parent->cast_to<Control>(); + if (parent_control) { + pos=parent_control->get_global_pos(); + } + } + Matrix32 trans=canvas->get_canvas_transform(); + editor_data->get_undo_redo().add_do_method(instanced_scene,"set_pos",(p_point-trans.get_origin())/trans.get_scale().x-pos); + + return true; +} + +void CanvasItemEditorViewport::_perform_drop_data(){ + _remove_preview(); + + Vector<String> error_files; + + editor_data->get_undo_redo().create_action(TTR("Create Node")); + + for (int i=0;i<selected_files.size();i++) { + String path=selected_files[i]; + RES res=ResourceLoader::load(path); + if (res.is_null()) { + continue; + } + String type=res->get_type(); + if (type=="ImageTexture") { + Node* child; + if (default_type=="Light2D") child=memnew(Light2D); + else if (default_type=="Particles2D") child=memnew(Particles2D); + else if (default_type=="Polygon2D") child=memnew(Polygon2D); + else if (default_type=="TouchScreenButton") child=memnew(TouchScreenButton); + else if (default_type=="TextureFrame") child=memnew(TextureFrame); + else if (default_type=="Patch9Frame") child=memnew(Patch9Frame); + else child=memnew(Sprite); // default + + _create_nodes(target_node, child, path, drop_pos); + } else if (type=="PackedScene") { + bool success=_create_instance(target_node, path, drop_pos); + if (!success) { + error_files.push_back(path); + } + } + } + + editor_data->get_undo_redo().commit_action(); + + if (error_files.size()>0) { + String files_str; + for (int i=0;i<error_files.size();i++) { + files_str += error_files[i].get_file().basename() + ","; + } + files_str=files_str.substr(0,files_str.length()-1); + accept->get_ok()->set_text(TTR("Ugh")); + accept->set_text(vformat(TTR("Error instancing scene from %s"),files_str.c_str())); + accept->popup_centered_minsize(); + } +} + +bool CanvasItemEditorViewport::can_drop_data(const Point2& p_point,const Variant& p_data) const { + Dictionary d=p_data; + if (d.has("type")) { + if (String(d["type"])=="files") { + Vector<String> files=d["files"]; + bool can_instance=false; + for (int i=0;i<files.size();i++) { // check if dragged files contain resource or scene can be created at least one + RES res=ResourceLoader::load(files[i]); + if (res.is_null()) { + continue; + } + String type=res->get_type(); + if (type=="PackedScene") { + Ref<PackedScene> sdata=ResourceLoader::load(files[i]); + Node* instanced_scene=sdata->instance(true); + if (!instanced_scene) { + continue; + } + memdelete(instanced_scene); + } + can_instance=true; + break; + } + if (can_instance) { + if (!preview->get_parent()){ // create preview only once + _create_preview(files); + } + Matrix32 trans=canvas->get_canvas_transform(); + preview->set_pos((p_point-trans.get_origin())/trans.get_scale().x); + label->set_text(vformat(TTR("Adding %s..."),default_type)); + } + return can_instance; + } + } + label->hide(); + return false; +} + +void CanvasItemEditorViewport::drop_data(const Point2& p_point,const Variant& p_data) { + bool is_shift=Input::get_singleton()->is_key_pressed(KEY_SHIFT); + bool is_alt=Input::get_singleton()->is_key_pressed(KEY_ALT); + + selected_files.clear(); + Dictionary d=p_data; + if (d.has("type") && String(d["type"])=="files"){ + selected_files=d["files"]; + } + + List<Node*> list=editor->get_editor_selection()->get_selected_node_list(); + if (list.size()==0) { + accept->get_ok()->set_text(TTR("OK :(")); + accept->set_text(TTR("No parent to instance a child at.")); + accept->popup_centered_minsize(); + _remove_preview(); + return; + } + if (list.size()!=1) { + accept->get_ok()->set_text(TTR("I see..")); + accept->set_text(TTR("This operation requires a single selected node.")); + accept->popup_centered_minsize(); + _remove_preview(); + return; + } + + target_node=list[0]; + if (is_shift && target_node!=editor->get_edited_scene()) { + target_node=target_node->get_parent(); + } + drop_pos=p_point; + + if (is_alt) { + List<BaseButton*> btn_list; + btn_group->get_button_list(&btn_list); + for (int i=0;i<btn_list.size();i++) { + CheckBox* check=btn_list[i]->cast_to<CheckBox>(); + check->set_pressed(check->get_text()==default_type); + } + selector_label->set_text(vformat(TTR("Add %s"),default_type)); + selector->popup_centered_minsize(); + } else { + _perform_drop_data(); + } +} + +void CanvasItemEditorViewport::_notification(int p_what) { + if (p_what==NOTIFICATION_ENTER_TREE) { + connect("mouse_exit",this,"_on_mouse_exit"); + } else if (p_what==NOTIFICATION_EXIT_TREE) { + disconnect("mouse_exit",this,"_on_mouse_exit"); + } +} + +void CanvasItemEditorViewport::_bind_methods() { + ObjectTypeDB::bind_method(_MD("_on_select_type"),&CanvasItemEditorViewport::_on_select_type); + ObjectTypeDB::bind_method(_MD("_on_change_type"),&CanvasItemEditorViewport::_on_change_type); + ObjectTypeDB::bind_method(_MD("_on_mouse_exit"),&CanvasItemEditorViewport::_on_mouse_exit); +} + +CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasItemEditor* p_canvas) { + default_type="Sprite"; + // Node2D + types.push_back("Sprite"); + types.push_back("Light2D"); + types.push_back("Particles2D"); + types.push_back("Polygon2D"); + types.push_back("TouchScreenButton"); + // Control + types.push_back("TextureFrame"); + types.push_back("Patch9Frame"); + + target_node=NULL; + editor=p_node; + editor_data=editor->get_scene_tree_dock()->get_editor_data(); + canvas=p_canvas; + preview=memnew( Node2D ); + accept=memnew( AcceptDialog ); + editor->get_gui_base()->add_child(accept); + + selector=memnew( WindowDialog ); + selector->set_title(TTR("Change default type")); + + VBoxContainer* vbc=memnew(VBoxContainer); + vbc->add_constant_override("separation",10*EDSCALE); + vbc->set_custom_minimum_size(Size2(200,260)*EDSCALE); + + selector_label=memnew(Label); + selector_label->set_align(Label::ALIGN_CENTER); + selector_label->set_valign(Label::VALIGN_BOTTOM); + selector_label->set_custom_minimum_size(Size2(0,30)*EDSCALE); + vbc->add_child(selector_label); + + btn_group=memnew( ButtonGroup ); + btn_group->set_h_size_flags(0); + btn_group->connect("button_selected", this, "_on_select_type"); + + for (int i=0;i<types.size();i++) { + CheckBox* check=memnew(CheckBox); + check->set_text(types[i]); + btn_group->add_child(check); + } + vbc->add_child(btn_group); + + Button* ok=memnew(Button); + ok->set_text(TTR("OK")); + ok->set_h_size_flags(0); + vbc->add_child(ok); + ok->connect("pressed", this, "_on_change_type"); + + selector->add_child(vbc); + editor->get_gui_base()->add_child(selector); + + label=memnew(Label); + label->add_color_override("font_color", Color(1,1,0,1)); + label->add_color_override("font_color_shadow", Color(0,0,0,1)); + label->add_constant_override("shadow_as_outline", 1*EDSCALE); + label->hide(); + editor->get_gui_base()->add_child(label); + + label_desc=memnew(Label); + label_desc->set_text(TTR("Drag & drop + Shift : Add node as sibling\nDrag & drop + Alt : Change node type")); + label_desc->add_color_override("font_color", Color(0.6,0.6,0.6,1)); + label_desc->add_color_override("font_color_shadow", Color(0.2,0.2,0.2,1)); + label_desc->add_constant_override("shadow_as_outline", 1*EDSCALE); + label_desc->add_constant_override("line_spacing", 0); + label_desc->hide(); + editor->get_gui_base()->add_child(label_desc); +} diff --git a/tools/editor/plugins/canvas_item_editor_plugin.h b/tools/editor/plugins/canvas_item_editor_plugin.h index 9f4bc46eb4..bbec078e02 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.h +++ b/tools/editor/plugins/canvas_item_editor_plugin.h @@ -31,17 +31,18 @@ #include "tools/editor/editor_plugin.h" #include "tools/editor/editor_node.h" +#include "scene/gui/button_group.h" +#include "scene/gui/check_box.h" +#include "scene/gui/label.h" #include "scene/gui/spin_box.h" #include "scene/gui/panel_container.h" #include "scene/gui/box_container.h" #include "scene/2d/canvas_item.h" - /** @author Juan Linietsky <reduzio@gmail.com> */ - - +class CanvasItemEditorViewport; class CanvasItemEditorSelectedItem : public Object { @@ -453,4 +454,49 @@ public: }; +class CanvasItemEditorViewport : public VBoxContainer { + OBJ_TYPE( CanvasItemEditorViewport, VBoxContainer ); + + String default_type; + Vector<String> types; + + Vector<String> selected_files; + Node* target_node; + Point2 drop_pos; + + EditorNode* editor; + EditorData* editor_data; + CanvasItemEditor* canvas; + Node2D* preview; + AcceptDialog* accept; + WindowDialog* selector; + Label* selector_label; + Label* label; + Label* label_desc; + ButtonGroup* btn_group; + + void _on_mouse_exit(); + void _on_select_type(Object* selected); + void _on_change_type(); + + void _create_preview(const Vector<String>& files) const; + void _remove_preview(); + + bool _cyclical_dependency_exists(const String& p_target_scene_path, Node* p_desired_node); + void _create_nodes(Node* parent, Node* child, String& path, const Point2& p_point); + bool _create_instance(Node* parent, String& path, const Point2& p_point); + void _perform_drop_data(); + + static void _bind_methods(); + +protected: + void _notification(int p_what); + +public: + virtual bool can_drop_data(const Point2& p_point,const Variant& p_data) const; + virtual void drop_data(const Point2& p_point,const Variant& p_data); + + CanvasItemEditorViewport(EditorNode *p_node, CanvasItemEditor* p_canvas); +}; + #endif diff --git a/tools/editor/scene_tree_dock.cpp b/tools/editor/scene_tree_dock.cpp index 56f10ff7f8..16f06c7ac9 100644 --- a/tools/editor/scene_tree_dock.cpp +++ b/tools/editor/scene_tree_dock.cpp @@ -81,7 +81,10 @@ void SceneTreeDock::_unhandled_key_input(InputEvent p_event) { _tool_selected(TOOL_DUPLICATE); } else if (ED_IS_SHORTCUT("scene_tree/add_script", p_event)) { - _tool_selected(TOOL_SCRIPT); + _tool_selected(TOOL_CREATE_SCRIPT); + } + else if (ED_IS_SHORTCUT("scene_tree/load_script", p_event)) { + _tool_selected(TOOL_LOAD_SCRIPT); } else if (ED_IS_SHORTCUT("scene_tree/move_up", p_event)) { _tool_selected(TOOL_MOVE_UP); @@ -266,6 +269,24 @@ void SceneTreeDock::_replace_with_branch_scene(const String& p_file,Node* base) scene_tree->set_selected(instanced_scene); } + +void SceneTreeDock::_file_selected(String p_file) { + RES p_script = ResourceLoader::load(p_file, "Script"); + if (p_script.is_null()) { + accept->get_ok()->set_text(TTR("Ugh")); + accept->set_text(vformat(TTR("Error loading script from %s"), p_file)); + accept->popup_centered_minsize(); + return; + } + + Node *selected = scene_tree->get_selected(); + if (!selected) + return; + selected->set_script(p_script.get_ref_ptr()); + editor->push_item(p_script.operator->()); + file_dialog->hide(); +} + bool SceneTreeDock::_cyclical_dependency_exists(const String& p_target_scene_path, Node* p_desired_node) { int childCount = p_desired_node->get_child_count(); @@ -358,7 +379,22 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { //groups_editor->set_current(current); //groups_editor->popup_centered_ratio(); } break; - case TOOL_SCRIPT: { + case TOOL_LOAD_SCRIPT: { + Node *selected = scene_tree->get_selected(); + if (!selected) + break; + + file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE); + + List<String> extensions; + ResourceLoader::get_recognized_extensions_for_type("Script", &extensions); + file_dialog->clear_filters(); + for (List<String>::Element *E = extensions.front(); E; E = E->next()) + file_dialog->add_filter("*." + E->get() + " ; " + E->get().to_upper()); + + file_dialog->popup_centered_ratio(); + } break; + case TOOL_CREATE_SCRIPT: { Node *selected = scene_tree->get_selected(); if (!selected) @@ -672,6 +708,7 @@ void SceneTreeDock::_notification(int p_what) { button_add->set_icon(get_icon("Add","EditorIcons")); button_instance->set_icon(get_icon("Instance","EditorIcons")); button_create_script->set_icon(get_icon("Script","EditorIcons")); + button_load_script->set_icon(get_icon("Script", "EditorIcons")); filter_icon->set_texture(get_icon("Zoom","EditorIcons")); @@ -1303,8 +1340,10 @@ void SceneTreeDock::_selection_changed() { if (selection_size==1 && EditorNode::get_singleton()->get_editor_selection()->get_selection().front()->key()->get_script().is_null()) { button_create_script->show(); + button_load_script->show(); } else { button_create_script->hide(); + button_load_script->hide(); } //tool_buttons[TOOL_MULTI_EDIT]->set_disabled(EditorNode::get_singleton()->get_editor_selection()->get_selection().size()<2); @@ -1721,6 +1760,15 @@ void SceneTreeDock::_files_dropped(Vector<String> p_files,NodePath p_to,int p_ty _perform_instance_scenes(p_files,node,to_pos); } +void SceneTreeDock::_script_dropped(String p_file, NodePath p_to) { + Ref<Script> scr = ResourceLoader::load(p_file); + ERR_FAIL_COND(!scr.is_valid()); + Node *n = get_node(p_to); + if (n) { + n->set_script(scr.get_ref_ptr()); + } +} + void SceneTreeDock::_nodes_dragged(Array p_nodes,NodePath p_to,int p_type) { Vector<Node*> nodes; @@ -1775,7 +1823,8 @@ void SceneTreeDock::_tree_rmb(const Vector2& p_menu_pos) { //menu->add_icon_item(get_icon("Groups","EditorIcons"),TTR("Edit Groups"),TOOL_GROUP); //menu->add_icon_item(get_icon("Connect","EditorIcons"),TTR("Edit Connections"),TOOL_CONNECT); menu->add_separator(); - menu->add_icon_shortcut(get_icon("Script","EditorIcons"),ED_GET_SHORTCUT("scene_tree/add_script"), TOOL_SCRIPT); + menu->add_icon_shortcut(get_icon("Script", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/add_script"), TOOL_CREATE_SCRIPT); + menu->add_icon_shortcut(get_icon("Script", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/load_script"), TOOL_LOAD_SCRIPT); menu->add_separator(); } @@ -1834,7 +1883,7 @@ void SceneTreeDock::_focus_node() { void SceneTreeDock::open_script_dialog(Node* p_for_node) { scene_tree->set_selected(p_for_node,false); - _tool_selected(TOOL_SCRIPT); + _tool_selected(TOOL_CREATE_SCRIPT); } void SceneTreeDock::_bind_methods() { @@ -1859,9 +1908,11 @@ void SceneTreeDock::_bind_methods() { ObjectTypeDB::bind_method(_MD("_new_scene_from"),&SceneTreeDock::_new_scene_from); ObjectTypeDB::bind_method(_MD("_nodes_dragged"),&SceneTreeDock::_nodes_dragged); ObjectTypeDB::bind_method(_MD("_files_dropped"),&SceneTreeDock::_files_dropped); + ObjectTypeDB::bind_method(_MD("_script_dropped"),&SceneTreeDock::_script_dropped); ObjectTypeDB::bind_method(_MD("_tree_rmb"),&SceneTreeDock::_tree_rmb); ObjectTypeDB::bind_method(_MD("_filter_changed"),&SceneTreeDock::_filter_changed); ObjectTypeDB::bind_method(_MD("_focus_node"),&SceneTreeDock::_focus_node); + ObjectTypeDB::bind_method(_MD("_file_selected"), &SceneTreeDock::_file_selected); ObjectTypeDB::bind_method(_MD("instance"),&SceneTreeDock::instance); @@ -1886,6 +1937,7 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelec ED_SHORTCUT("scene_tree/instance_scene",TTR("Instance Child Scene")); ED_SHORTCUT("scene_tree/change_node_type", TTR("Change Type")); ED_SHORTCUT("scene_tree/add_script", TTR("Add Script")); + ED_SHORTCUT("scene_tree/load_script", TTR("Load Script")); ED_SHORTCUT("scene_tree/move_up", TTR("Move Up"), KEY_MASK_CMD | KEY_UP); ED_SHORTCUT("scene_tree/move_down", TTR("Move Down"), KEY_MASK_CMD | KEY_DOWN); ED_SHORTCUT("scene_tree/duplicate", TTR("Duplicate"),KEY_MASK_CMD | KEY_D); @@ -1922,12 +1974,19 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelec tb = memnew( ToolButton ); - tb->connect("pressed",this,"_tool_selected",make_binds(TOOL_SCRIPT, false)); + tb->connect("pressed",this,"_tool_selected",make_binds(TOOL_CREATE_SCRIPT, false)); tb->set_tooltip(TTR("Create a new script for the selected node.")); tb->set_shortcut(ED_GET_SHORTCUT("scene_tree/add_script")); filter_hbc->add_child(tb); button_create_script=tb; + tb = memnew(ToolButton); + tb->connect("pressed", this, "_tool_selected", make_binds(TOOL_LOAD_SCRIPT, false)); + tb->set_tooltip(TTR("Load a script for the selected node.")); + tb->set_shortcut(ED_GET_SHORTCUT("scene_tree/load_script")); + filter_hbc->add_child(tb); + button_load_script = tb; + scene_tree = memnew( SceneTreeEditor(false,true,true )); vbc->add_child(scene_tree); @@ -1941,6 +2000,7 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelec scene_tree->connect("open_script",this,"_script_open_request"); scene_tree->connect("nodes_rearranged",this,"_nodes_dragged"); scene_tree->connect("files_dropped",this,"_files_dropped"); + scene_tree->connect("script_dropped",this,"_script_dropped"); scene_tree->connect("nodes_dragged",this,"_nodes_drag_begin"); scene_tree->get_scene_tree()->connect("item_double_clicked", this, "_focus_node"); @@ -1955,6 +2015,11 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelec add_child(create_dialog); create_dialog->connect("create",this,"_create"); + file_dialog = memnew(EditorFileDialog); + add_child(file_dialog); + file_dialog->hide(); + file_dialog->connect("file_selected", this, "_file_selected"); + //groups_editor = memnew( GroupsEditor ); //add_child(groups_editor); //groups_editor->set_undo_redo(&editor_data->get_undo_redo()); diff --git a/tools/editor/scene_tree_dock.h b/tools/editor/scene_tree_dock.h index 8933a03883..36d4a6d208 100644 --- a/tools/editor/scene_tree_dock.h +++ b/tools/editor/scene_tree_dock.h @@ -58,7 +58,8 @@ class SceneTreeDock : public VBoxContainer { TOOL_REPLACE, TOOL_CONNECT, TOOL_GROUP, - TOOL_SCRIPT, + TOOL_CREATE_SCRIPT, + TOOL_LOAD_SCRIPT, TOOL_MOVE_UP, TOOL_MOVE_DOWN, TOOL_DUPLICATE, @@ -75,10 +76,12 @@ class SceneTreeDock : public VBoxContainer { int current_option; CreateDialog *create_dialog; + EditorFileDialog *file_dialog; ToolButton *button_add; ToolButton *button_instance; ToolButton *button_create_script; + ToolButton *button_load_script; SceneTreeEditor *scene_tree; @@ -147,6 +150,7 @@ class SceneTreeDock : public VBoxContainer { void _nodes_dragged(Array p_nodes,NodePath p_to,int p_type); void _files_dropped(Vector<String> p_files,NodePath p_to,int p_type); + void _script_dropped(String p_file, NodePath p_to); void _tree_rmb(const Vector2& p_menu_pos); @@ -155,6 +159,7 @@ class SceneTreeDock : public VBoxContainer { void _perform_instance_scenes(const Vector<String>& p_files,Node* parent,int p_pos); void _replace_with_branch_scene(const String& p_file,Node* base); + void _file_selected(String p_file); protected: void _notification(int p_what); @@ -174,7 +179,7 @@ public: void fill_path_renames(Node* p_node, Node *p_new_parent, List<Pair<NodePath,NodePath> > *p_renames); void perform_node_renames(Node* p_base,List<Pair<NodePath,NodePath> > *p_renames, Map<Ref<Animation>, Set<int> > *r_rem_anims=NULL); SceneTreeEditor *get_tree_editor() { return scene_tree; } - + EditorData *get_editor_data() { return editor_data; } void open_script_dialog(Node* p_for_node); SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelection *p_editor_selection,EditorData &p_editor_data); diff --git a/tools/editor/scene_tree_editor.cpp b/tools/editor/scene_tree_editor.cpp index 53bfe8cc57..f5628d0c8f 100644 --- a/tools/editor/scene_tree_editor.cpp +++ b/tools/editor/scene_tree_editor.cpp @@ -971,6 +971,10 @@ Variant SceneTreeEditor::get_drag_data_fw(const Point2& p_point,Control* p_from) return drag_data; } +bool SceneTreeEditor::_is_script_type(const StringName &p_type) const { + return (script_types->find(p_type)); +} + bool SceneTreeEditor::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const { if (!can_rename) @@ -998,9 +1002,13 @@ bool SceneTreeEditor::can_drop_data_fw(const Point2& p_point,const Variant& p_da if (files.size()==0) return false; //weird + if (_is_script_type(EditorFileSystem::get_singleton()->get_file_type(files[0]))) { + tree->set_drop_mode_flags(Tree::DROP_MODE_ON_ITEM); + return true; + } for(int i=0;i<files.size();i++) { - String file = files[0]; + String file = files[i]; String ftype = EditorFileSystem::get_singleton()->get_file_type(file); if (ftype!="PackedScene") return false; @@ -1044,7 +1052,15 @@ void SceneTreeEditor::drop_data_fw(const Point2& p_point,const Variant& p_data,C if (String(d["type"])=="files") { - emit_signal("files_dropped",d["files"],np,section); + Vector<String> files = d["files"]; + + + String ftype = EditorFileSystem::get_singleton()->get_file_type(files[0]); + if (_is_script_type(ftype)) { + emit_signal("script_dropped", files[0],np); + } else { + emit_signal("files_dropped",files,np,section); + } } } @@ -1113,6 +1129,7 @@ void SceneTreeEditor::_bind_methods() { ADD_SIGNAL( MethodInfo("nodes_dragged") ); ADD_SIGNAL( MethodInfo("nodes_rearranged",PropertyInfo(Variant::ARRAY,"paths"),PropertyInfo(Variant::NODE_PATH,"to_path"),PropertyInfo(Variant::INT,"type") ) ); ADD_SIGNAL( MethodInfo("files_dropped",PropertyInfo(Variant::STRING_ARRAY,"files"),PropertyInfo(Variant::NODE_PATH,"to_path"),PropertyInfo(Variant::INT,"type") ) ); + ADD_SIGNAL( MethodInfo("script_dropped",PropertyInfo(Variant::STRING,"file"),PropertyInfo(Variant::NODE_PATH,"to_path"))); ADD_SIGNAL( MethodInfo("rmb_pressed",PropertyInfo(Variant::VECTOR2,"pos")) ) ; ADD_SIGNAL( MethodInfo("open") ); @@ -1209,12 +1226,16 @@ SceneTreeEditor::SceneTreeEditor(bool p_label,bool p_can_rename, bool p_can_open update_timer->set_wait_time(0.5); add_child(update_timer); + script_types = memnew(List<StringName>); + ObjectTypeDB::get_inheriters_from("Script", script_types); + } SceneTreeEditor::~SceneTreeEditor() { + memdelete(script_types); } diff --git a/tools/editor/scene_tree_editor.h b/tools/editor/scene_tree_editor.h index 79b7a64468..12d85ecdeb 100644 --- a/tools/editor/scene_tree_editor.h +++ b/tools/editor/scene_tree_editor.h @@ -137,6 +137,9 @@ class SceneTreeEditor : public Control { Timer* update_timer; + List<StringName> *script_types; + bool _is_script_type(const StringName &p_type) const; + public: void set_filter(const String& p_filter); |