/*************************************************************************/ /* call_dialog.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ /* "Software"), to deal in the Software without restriction, including */ /* without limitation the rights to use, copy, modify, merge, publish, */ /* distribute, sublicense, and/or sell copies of the Software, and to */ /* permit persons to whom the Software is furnished to do so, subject to */ /* the following conditions: */ /* */ /* The above copyright notice and this permission notice shall be */ /* included in all copies or substantial portions of the Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "call_dialog.h" #include "object_type_db.h" #include "print_string.h" #include "scene/gui/label.h" class CallDialogParams : public Object { OBJ_TYPE(CallDialogParams, Object); public: bool _set(const StringName &p_name, const Variant &p_value) { values[p_name] = p_value; return true; } bool _get(const StringName &p_name, Variant &r_ret) const { if (values.has(p_name)) { r_ret = values[p_name]; return true; } return false; } void _get_property_list(List *p_list) const { for (int i = 0; i < method.arguments.size(); i++) p_list->push_back(method.arguments[i]); } MethodInfo method; HashMap values; CallDialogParams() {} }; void CallDialog::_notification(int p_what) { if (p_what == NOTIFICATION_READY) { call->connect("pressed", this, "_call"); cancel->connect("pressed", this, "_cancel"); //filter->get_path()->connect("text_changed", this,"_text_changed"); _update_method_list(); } if (p_what == NOTIFICATION_EXIT_TREE) { call->disconnect("pressed", this, "_call"); cancel->disconnect("pressed", this, "_cancel"); //filter->get_path()->connect("text_changed", this,"_text_changed"); _update_method_list(); } if (p_what == NOTIFICATION_DRAW) { RID ci = get_canvas_item(); get_stylebox("panel", "PopupMenu")->draw(ci, Rect2(Point2(), get_size())); } } void CallDialog::_call() { if (!tree->get_selected()) return; TreeItem *item = tree->get_selected(); ERR_FAIL_COND(!item); int idx = item->get_metadata(0); ERR_FAIL_INDEX(idx, methods.size()); MethodInfo &m = methods[idx]; Variant args[VARIANT_ARG_MAX]; for (int i = 0; i < VARIANT_ARG_MAX; i++) { if (i >= m.arguments.size()) continue; if (call_params->values.has(m.arguments[i].name)) args[i] = call_params->values[m.arguments[i].name]; } Variant ret = object->call(m.name, args[0], args[1], args[2], args[3], args[4]); if (ret.get_type() != Variant::NIL) return_value->set_text(ret); else return_value->set_text(""); } void CallDialog::_cancel() { hide(); } void CallDialog::_item_selected() { TreeItem *item = tree->get_selected(); ERR_FAIL_COND(!item); if (item->get_metadata(0).get_type() == Variant::NIL) { call->set_disabled(true); return; } call->set_disabled(false); int idx = item->get_metadata(0); ERR_FAIL_INDEX(idx, methods.size()); MethodInfo &m = methods[idx]; call_params->values.clear(); call_params->method = m; property_editor->edit(call_params); property_editor->update_tree(); } void CallDialog::_update_method_list() { tree->clear(); if (!object) return; TreeItem *root = tree->create_item(); List method_list; object->get_method_list(&method_list); method_list.sort(); methods.clear(); List inheritance_list; String type = object->get_type(); while (type != "") { inheritance_list.push_back(type); type = ObjectTypeDB::type_inherits_from(type); } TreeItem *selected_item = NULL; for (int i = 0; i < inheritance_list.size(); i++) { String type = inheritance_list[i]; String parent_type = ObjectTypeDB::type_inherits_from(type); TreeItem *type_item = NULL; List::Element *N, *E = method_list.front(); while (E) { N = E->next(); if (parent_type != "" && ObjectTypeDB::get_method(parent_type, E->get().name) != NULL) { E = N; continue; } if (!type_item) { type_item = tree->create_item(root); type_item->set_text(0, type); if (has_icon(type, "EditorIcons")) type_item->set_icon(0, get_icon(type, "EditorIcons")); } TreeItem *method_item = tree->create_item(type_item); method_item->set_text(0, E->get().name); method_item->set_metadata(0, methods.size()); if (E->get().name == selected) selected_item = method_item; methods.push_back(E->get()); method_list.erase(E); E = N; } } if (selected_item) selected_item->select(0); } void CallDialog::_bind_methods() { ObjectTypeDB::bind_method("_call", &CallDialog::_call); ObjectTypeDB::bind_method("_cancel", &CallDialog::_cancel); ObjectTypeDB::bind_method("_item_selected", &CallDialog::_item_selected); } void CallDialog::set_object(Object *p_object, StringName p_selected) { object = p_object; selected = p_selected; property_editor->edit(NULL); call->set_disabled(true); return_value->clear(); _update_method_list(); method_label->set_text(vformat(TTR("Method List For '%s':"), p_object->get_type())); } CallDialog::CallDialog() { object = NULL; call = memnew(Button); call->set_anchor(MARGIN_LEFT, ANCHOR_END); call->set_anchor(MARGIN_TOP, ANCHOR_END); call->set_anchor(MARGIN_RIGHT, ANCHOR_END); call->set_anchor(MARGIN_BOTTOM, ANCHOR_END); call->set_begin(Point2(70, 29)); call->set_end(Point2(15, 15)); call->set_text(TTR("Call")); add_child(call); cancel = memnew(Button); cancel->set_anchor(MARGIN_TOP, ANCHOR_END); cancel->set_anchor(MARGIN_BOTTOM, ANCHOR_END); cancel->set_begin(Point2(15, 29)); cancel->set_end(Point2(70, 15)); cancel->set_text(TTR("Close")); add_child(cancel); tree = memnew(Tree); tree->set_anchor(MARGIN_RIGHT, ANCHOR_RATIO); tree->set_anchor(MARGIN_BOTTOM, ANCHOR_END); tree->set_begin(Point2(20, 50)); tree->set_margin(MARGIN_BOTTOM, 44); tree->set_margin(MARGIN_RIGHT, 0.5); tree->set_select_mode(Tree::SELECT_ROW); add_child(tree); tree->connect("item_selected", this, "_item_selected"); tree->set_hide_root(true); property_editor = memnew(PropertyEditor); property_editor->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 15); property_editor->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 50); property_editor->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_RATIO, 0.55); property_editor->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 90); property_editor->get_scene_tree()->set_hide_root(true); property_editor->hide_top_label(); add_child(property_editor); method_label = memnew(Label); method_label->set_pos(Point2(15, 25)); method_label->set_text(TTR("Method List:")); add_child(method_label); Label *label = memnew(Label); label->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_RATIO, 0.53); label->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 25); label->set_text(TTR("Arguments:")); add_child(label); return_label = memnew(Label); return_label->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_RATIO, 0.53); return_label->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, 85); return_label->set_text(TTR("Return:")); add_child(return_label); return_value = memnew(LineEdit); return_value->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_RATIO, 0.55); return_value->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 15); return_value->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, 65); add_child(return_value); /* label = memnew( Label ); label->set_anchor( MARGIN_TOP, ANCHOR_END ); label->set_anchor( MARGIN_BOTTOM, ANCHOR_END ); label->set_begin( Point2( 15,54) ); label->set_end( Point2( 16,44) ); label->set_text("Parameters:"); add_child(label); */ call_params = memnew(CallDialogParams); set_as_toplevel(true); } CallDialog::~CallDialog() { memdelete(call_params); }