animation_blend_tree_editor_plugin.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845
  1. #include "animation_blend_tree_editor_plugin.h"
  2. #include "core/io/resource_loader.h"
  3. #include "core/project_settings.h"
  4. #include "os/input.h"
  5. #include "os/keyboard.h"
  6. #include "scene/animation/animation_player.h"
  7. #include "scene/gui/menu_button.h"
  8. #include "scene/gui/panel.h"
  9. #include "scene/main/viewport.h"
  10. void AnimationNodeBlendTreeEditor::edit(AnimationNodeBlendTree *p_blend_tree) {
  11. if (blend_tree.is_valid()) {
  12. blend_tree->disconnect("removed_from_graph", this, "_removed_from_graph");
  13. }
  14. if (p_blend_tree) {
  15. blend_tree = Ref<AnimationNodeBlendTree>(p_blend_tree);
  16. } else {
  17. blend_tree.unref();
  18. }
  19. if (blend_tree.is_null()) {
  20. hide();
  21. } else {
  22. blend_tree->connect("removed_from_graph", this, "_removed_from_graph");
  23. _update_graph();
  24. }
  25. }
  26. void AnimationNodeBlendTreeEditor::add_custom_type(const String &p_name, const Ref<Script> &p_script) {
  27. for (int i = 0; i < add_options.size(); i++) {
  28. ERR_FAIL_COND(add_options[i].script == p_script);
  29. }
  30. AddOption ao;
  31. ao.name = p_name;
  32. ao.script = p_script;
  33. add_options.push_back(ao);
  34. _update_options_menu();
  35. }
  36. void AnimationNodeBlendTreeEditor::remove_custom_type(const Ref<Script> &p_script) {
  37. for (int i = 0; i < add_options.size(); i++) {
  38. if (add_options[i].script == p_script) {
  39. add_options.remove(i);
  40. return;
  41. }
  42. }
  43. _update_options_menu();
  44. }
  45. void AnimationNodeBlendTreeEditor::_update_options_menu() {
  46. add_node->get_popup()->clear();
  47. for (int i = 0; i < add_options.size(); i++) {
  48. add_node->get_popup()->add_item(add_options[i].name);
  49. }
  50. }
  51. Size2 AnimationNodeBlendTreeEditor::get_minimum_size() const {
  52. return Size2(10, 200);
  53. }
  54. void AnimationNodeBlendTreeEditor::_update_graph() {
  55. if (updating)
  56. return;
  57. graph->set_scroll_ofs(blend_tree->get_graph_offset() * EDSCALE);
  58. if (blend_tree->get_parent().is_valid()) {
  59. goto_parent->show();
  60. } else {
  61. goto_parent->hide();
  62. }
  63. graph->clear_connections();
  64. //erase all nodes
  65. for (int i = 0; i < graph->get_child_count(); i++) {
  66. if (Object::cast_to<GraphNode>(graph->get_child(i))) {
  67. memdelete(graph->get_child(i));
  68. i--;
  69. }
  70. }
  71. animations.clear();
  72. List<StringName> nodes;
  73. blend_tree->get_node_list(&nodes);
  74. for (List<StringName>::Element *E = nodes.front(); E; E = E->next()) {
  75. GraphNode *node = memnew(GraphNode);
  76. graph->add_child(node);
  77. Ref<AnimationNode> agnode = blend_tree->get_node(E->get());
  78. if (!agnode->is_connected("changed", this, "_node_changed")) {
  79. agnode->connect("changed", this, "_node_changed", varray(agnode->get_instance_id()), CONNECT_DEFERRED);
  80. }
  81. node->set_offset(agnode->get_position() * EDSCALE);
  82. node->set_title(agnode->get_caption());
  83. node->set_name(E->get());
  84. int base = 0;
  85. if (String(E->get()) != "output") {
  86. LineEdit *name = memnew(LineEdit);
  87. name->set_text(E->get());
  88. name->set_expand_to_text_length(true);
  89. node->add_child(name);
  90. node->set_slot(0, false, 0, Color(), true, 0, get_color("font_color", "Label"));
  91. name->connect("text_entered", this, "_node_renamed", varray(agnode));
  92. name->connect("focus_exited", this, "_node_renamed_focus_out", varray(name, agnode));
  93. base = 1;
  94. node->set_show_close_button(true);
  95. node->connect("close_request", this, "_delete_request", varray(E->get()), CONNECT_DEFERRED);
  96. }
  97. for (int i = 0; i < agnode->get_input_count(); i++) {
  98. Label *in_name = memnew(Label);
  99. node->add_child(in_name);
  100. in_name->set_text(agnode->get_input_name(i));
  101. node->set_slot(base + i, true, 0, get_color("font_color", "Label"), false, 0, Color());
  102. }
  103. node->connect("dragged", this, "_node_dragged", varray(agnode));
  104. if (EditorNode::get_singleton()->item_has_editor(agnode.ptr())) {
  105. node->add_child(memnew(HSeparator));
  106. Button *open_in_editor = memnew(Button);
  107. open_in_editor->set_text(TTR("Open Editor"));
  108. open_in_editor->set_icon(get_icon("Edit", "EditorIcons"));
  109. node->add_child(open_in_editor);
  110. open_in_editor->connect("pressed", this, "_open_in_editor", varray(E->get()), CONNECT_DEFERRED);
  111. open_in_editor->set_h_size_flags(SIZE_SHRINK_CENTER);
  112. }
  113. if (agnode->has_filter()) {
  114. node->add_child(memnew(HSeparator));
  115. Button *edit_filters = memnew(Button);
  116. edit_filters->set_text(TTR("Edit Filters"));
  117. edit_filters->set_icon(get_icon("AnimationFilter", "EditorIcons"));
  118. node->add_child(edit_filters);
  119. edit_filters->connect("pressed", this, "_edit_filters", varray(E->get()), CONNECT_DEFERRED);
  120. edit_filters->set_h_size_flags(SIZE_SHRINK_CENTER);
  121. }
  122. Ref<AnimationNodeAnimation> anim = agnode;
  123. if (anim.is_valid()) {
  124. MenuButton *mb = memnew(MenuButton);
  125. mb->set_text(anim->get_animation());
  126. mb->set_icon(get_icon("Animation", "EditorIcons"));
  127. Array options;
  128. node->add_child(memnew(HSeparator));
  129. node->add_child(mb);
  130. ProgressBar *pb = memnew(ProgressBar);
  131. AnimationGraphPlayer *player = anim->get_graph_player();
  132. if (player->has_node(player->get_animation_player())) {
  133. AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(player->get_node(player->get_animation_player()));
  134. if (ap) {
  135. List<StringName> anims;
  136. ap->get_animation_list(&anims);
  137. for (List<StringName>::Element *F = anims.front(); F; F = F->next()) {
  138. mb->get_popup()->add_item(F->get());
  139. options.push_back(F->get());
  140. }
  141. if (ap->has_animation(anim->get_animation())) {
  142. pb->set_max(ap->get_animation(anim->get_animation())->get_length());
  143. }
  144. }
  145. }
  146. pb->set_percent_visible(false);
  147. animations[E->get()] = pb;
  148. node->add_child(pb);
  149. mb->get_popup()->connect("index_pressed", this, "_anim_selected", varray(options, E->get()), CONNECT_DEFERRED);
  150. }
  151. Ref<AnimationNodeOneShot> oneshot = agnode;
  152. if (oneshot.is_valid()) {
  153. HBoxContainer *play_stop = memnew(HBoxContainer);
  154. play_stop->add_spacer();
  155. Button *play = memnew(Button);
  156. play->set_icon(get_icon("Play", "EditorIcons"));
  157. play->connect("pressed", this, "_oneshot_start", varray(E->get()), CONNECT_DEFERRED);
  158. play_stop->add_child(play);
  159. Button *stop = memnew(Button);
  160. stop->set_icon(get_icon("Stop", "EditorIcons"));
  161. stop->connect("pressed", this, "_oneshot_stop", varray(E->get()), CONNECT_DEFERRED);
  162. play_stop->add_child(stop);
  163. play_stop->add_spacer();
  164. node->add_child(play_stop);
  165. }
  166. }
  167. List<AnimationNodeBlendTree::NodeConnection> connections;
  168. blend_tree->get_node_connections(&connections);
  169. for (List<AnimationNodeBlendTree::NodeConnection>::Element *E = connections.front(); E; E = E->next()) {
  170. StringName from = E->get().output_node;
  171. StringName to = E->get().input_node;
  172. int to_idx = E->get().input_index;
  173. graph->connect_node(from, 0, to, to_idx);
  174. }
  175. }
  176. void AnimationNodeBlendTreeEditor::_add_node(int p_idx) {
  177. ERR_FAIL_INDEX(p_idx, add_options.size());
  178. Ref<AnimationNode> anode;
  179. if (add_options[p_idx].type != String()) {
  180. AnimationNode *an = Object::cast_to<AnimationNode>(ClassDB::instance(add_options[p_idx].type));
  181. ERR_FAIL_COND(!an);
  182. anode = Ref<AnimationNode>(an);
  183. } else {
  184. ERR_FAIL_COND(add_options[p_idx].script.is_null());
  185. String base_type = add_options[p_idx].script->get_instance_base_type();
  186. AnimationNode *an = Object::cast_to<AnimationNode>(ClassDB::instance(base_type));
  187. ERR_FAIL_COND(!an);
  188. anode = Ref<AnimationNode>(an);
  189. anode->set_script(add_options[p_idx].script.get_ref_ptr());
  190. }
  191. Point2 instance_pos = graph->get_scroll_ofs() + graph->get_size() * 0.5;
  192. anode->set_position(instance_pos);
  193. String base_name = add_options[p_idx].name;
  194. int base = 1;
  195. String name = base_name;
  196. while (blend_tree->has_node(name)) {
  197. base++;
  198. name = base_name + " " + itos(base);
  199. }
  200. undo_redo->create_action("Add Node to BlendTree");
  201. undo_redo->add_do_method(blend_tree.ptr(), "add_node", name, anode);
  202. undo_redo->add_undo_method(blend_tree.ptr(), "remove_node", name);
  203. undo_redo->add_do_method(this, "_update_graph");
  204. undo_redo->add_undo_method(this, "_update_graph");
  205. undo_redo->commit_action();
  206. }
  207. void AnimationNodeBlendTreeEditor::_node_dragged(const Vector2 &p_from, const Vector2 &p_to, Ref<AnimationNode> p_node) {
  208. updating = true;
  209. undo_redo->create_action("Node Moved");
  210. undo_redo->add_do_method(p_node.ptr(), "set_position", p_to / EDSCALE);
  211. undo_redo->add_undo_method(p_node.ptr(), "set_position", p_from / EDSCALE);
  212. undo_redo->add_do_method(this, "_update_graph");
  213. undo_redo->add_undo_method(this, "_update_graph");
  214. undo_redo->commit_action();
  215. updating = false;
  216. }
  217. void AnimationNodeBlendTreeEditor::_connection_request(const String &p_from, int p_from_index, const String &p_to, int p_to_index) {
  218. AnimationNodeBlendTree::ConnectionError err = blend_tree->can_connect_node(p_to, p_to_index, p_from);
  219. if (err != AnimationNodeBlendTree::CONNECTION_OK) {
  220. EditorNode::get_singleton()->show_warning(TTR("Unable to connect, port may be in use or connection may be invalid."));
  221. return;
  222. }
  223. undo_redo->create_action("Nodes Connected");
  224. undo_redo->add_do_method(blend_tree.ptr(), "connect_node", p_to, p_to_index, p_from);
  225. undo_redo->add_undo_method(blend_tree.ptr(), "disconnect_node", p_to, p_to_index, p_from);
  226. undo_redo->add_do_method(this, "_update_graph");
  227. undo_redo->add_undo_method(this, "_update_graph");
  228. undo_redo->commit_action();
  229. }
  230. void AnimationNodeBlendTreeEditor::_disconnection_request(const String &p_from, int p_from_index, const String &p_to, int p_to_index) {
  231. graph->disconnect_node(p_from, p_from_index, p_to, p_to_index);
  232. updating = true;
  233. undo_redo->create_action("Nodes Disconnected");
  234. undo_redo->add_do_method(blend_tree.ptr(), "disconnect_node", p_to, p_to_index);
  235. undo_redo->add_undo_method(blend_tree.ptr(), "connect_node", p_to, p_to_index, p_from);
  236. undo_redo->add_do_method(this, "_update_graph");
  237. undo_redo->add_undo_method(this, "_update_graph");
  238. undo_redo->commit_action();
  239. updating = false;
  240. }
  241. void AnimationNodeBlendTreeEditor::_anim_selected(int p_index, Array p_options, const String &p_node) {
  242. String option = p_options[p_index];
  243. Ref<AnimationNodeAnimation> anim = blend_tree->get_node(p_node);
  244. ERR_FAIL_COND(!anim.is_valid());
  245. undo_redo->create_action("Set Animation");
  246. undo_redo->add_do_method(anim.ptr(), "set_animation", option);
  247. undo_redo->add_undo_method(anim.ptr(), "set_animation", anim->get_animation());
  248. undo_redo->add_do_method(this, "_update_graph");
  249. undo_redo->add_undo_method(this, "_update_graph");
  250. undo_redo->commit_action();
  251. }
  252. void AnimationNodeBlendTreeEditor::_delete_request(const String &p_which) {
  253. undo_redo->create_action("Delete Node");
  254. undo_redo->add_do_method(blend_tree.ptr(), "remove_node", p_which);
  255. undo_redo->add_undo_method(blend_tree.ptr(), "add_node", p_which, blend_tree->get_node(p_which));
  256. List<AnimationNodeBlendTree::NodeConnection> conns;
  257. blend_tree->get_node_connections(&conns);
  258. for (List<AnimationNodeBlendTree::NodeConnection>::Element *E = conns.front(); E; E = E->next()) {
  259. if (E->get().output_node == p_which || E->get().input_node == p_which) {
  260. undo_redo->add_undo_method(blend_tree.ptr(), "connect_node", E->get().input_node, E->get().input_index, E->get().output_node);
  261. }
  262. }
  263. undo_redo->add_do_method(this, "_update_graph");
  264. undo_redo->add_undo_method(this, "_update_graph");
  265. undo_redo->commit_action();
  266. }
  267. void AnimationNodeBlendTreeEditor::_oneshot_start(const StringName &p_name) {
  268. Ref<AnimationNodeOneShot> os = blend_tree->get_node(p_name);
  269. ERR_FAIL_COND(!os.is_valid());
  270. os->start();
  271. }
  272. void AnimationNodeBlendTreeEditor::_oneshot_stop(const StringName &p_name) {
  273. Ref<AnimationNodeOneShot> os = blend_tree->get_node(p_name);
  274. ERR_FAIL_COND(!os.is_valid());
  275. os->stop();
  276. }
  277. void AnimationNodeBlendTreeEditor::_node_selected(Object *p_node) {
  278. GraphNode *gn = Object::cast_to<GraphNode>(p_node);
  279. ERR_FAIL_COND(!gn);
  280. String name = gn->get_name();
  281. Ref<AnimationNode> anode = blend_tree->get_node(name);
  282. ERR_FAIL_COND(!anode.is_valid());
  283. EditorNode::get_singleton()->push_item(anode.ptr(), "", true);
  284. }
  285. void AnimationNodeBlendTreeEditor::_open_in_editor(const String &p_which) {
  286. Ref<AnimationNode> an = blend_tree->get_node(p_which);
  287. ERR_FAIL_COND(!an.is_valid())
  288. EditorNode::get_singleton()->edit_item(an.ptr());
  289. }
  290. void AnimationNodeBlendTreeEditor::_open_parent() {
  291. if (blend_tree->get_parent().is_valid()) {
  292. EditorNode::get_singleton()->edit_item(blend_tree->get_parent().ptr());
  293. }
  294. }
  295. void AnimationNodeBlendTreeEditor::_filter_toggled() {
  296. updating = true;
  297. undo_redo->create_action("Toggle filter on/off");
  298. undo_redo->add_do_method(_filter_edit.ptr(), "set_filter_enabled", filter_enabled->is_pressed());
  299. undo_redo->add_undo_method(_filter_edit.ptr(), "set_filter_enabled", _filter_edit->is_filter_enabled());
  300. undo_redo->add_do_method(this, "_update_filters", _filter_edit);
  301. undo_redo->add_undo_method(this, "_update_filters", _filter_edit);
  302. undo_redo->commit_action();
  303. updating = false;
  304. }
  305. void AnimationNodeBlendTreeEditor::_filter_edited() {
  306. TreeItem *edited = filters->get_edited();
  307. ERR_FAIL_COND(!edited);
  308. NodePath edited_path = edited->get_metadata(0);
  309. bool filtered = edited->is_checked(0);
  310. updating = true;
  311. undo_redo->create_action("Change filter");
  312. undo_redo->add_do_method(_filter_edit.ptr(), "set_filter_path", edited_path, filtered);
  313. undo_redo->add_undo_method(_filter_edit.ptr(), "set_filter_path", edited_path, _filter_edit->is_path_filtered(edited_path));
  314. undo_redo->add_do_method(this, "_update_filters", _filter_edit);
  315. undo_redo->add_undo_method(this, "_update_filters", _filter_edit);
  316. undo_redo->commit_action();
  317. updating = false;
  318. }
  319. bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &anode) {
  320. if (updating || _filter_edit != anode)
  321. return false;
  322. NodePath player_path = anode->get_graph_player()->get_animation_player();
  323. if (!anode->get_graph_player()->has_node(player_path)) {
  324. EditorNode::get_singleton()->show_warning(TTR("No animation player set, so unable to retrieve track names."));
  325. return false;
  326. }
  327. AnimationPlayer *player = Object::cast_to<AnimationPlayer>(anode->get_graph_player()->get_node(player_path));
  328. if (!player) {
  329. EditorNode::get_singleton()->show_warning(TTR("Player path set is invalid, so unable to retrieve track names."));
  330. return false;
  331. }
  332. Node *base = player->get_node(player->get_root());
  333. if (!base) {
  334. EditorNode::get_singleton()->show_warning(TTR("Animation player has no valid root node path, so unable to retrieve track names."));
  335. return false;
  336. }
  337. updating = true;
  338. Set<String> paths;
  339. {
  340. List<StringName> animations;
  341. player->get_animation_list(&animations);
  342. for (List<StringName>::Element *E = animations.front(); E; E = E->next()) {
  343. Ref<Animation> anim = player->get_animation(E->get());
  344. for (int i = 0; i < anim->get_track_count(); i++) {
  345. paths.insert(anim->track_get_path(i));
  346. }
  347. }
  348. }
  349. filter_enabled->set_pressed(anode->is_filter_enabled());
  350. filters->clear();
  351. TreeItem *root = filters->create_item();
  352. Map<String, TreeItem *> parenthood;
  353. for (Set<String>::Element *E = paths.front(); E; E = E->next()) {
  354. NodePath path = E->get();
  355. TreeItem *ti = NULL;
  356. String accum;
  357. for (int i = 0; i < path.get_name_count(); i++) {
  358. String name = path.get_name(i);
  359. if (accum != String()) {
  360. accum += "/";
  361. }
  362. accum += name;
  363. if (!parenthood.has(accum)) {
  364. if (ti) {
  365. ti = filters->create_item(ti);
  366. } else {
  367. ti = filters->create_item(root);
  368. }
  369. parenthood[accum] = ti;
  370. ti->set_text(0, name);
  371. ti->set_selectable(0, false);
  372. ti->set_editable(0, false);
  373. if (base->has_node(accum)) {
  374. Node *node = base->get_node(accum);
  375. if (has_icon(node->get_class(), "EditorIcons")) {
  376. ti->set_icon(0, get_icon(node->get_class(), "EditorIcons"));
  377. } else {
  378. ti->set_icon(0, get_icon("Node", "EditorIcons"));
  379. }
  380. }
  381. } else {
  382. ti = parenthood[accum];
  383. }
  384. }
  385. Node *node = NULL;
  386. if (base->has_node(accum)) {
  387. node = base->get_node(accum);
  388. }
  389. if (!node)
  390. continue; //no node, cant edit
  391. if (path.get_subname_count()) {
  392. String concat = path.get_concatenated_subnames();
  393. Skeleton *skeleton = Object::cast_to<Skeleton>(node);
  394. if (skeleton && skeleton->find_bone(concat) != -1) {
  395. //path in skeleton
  396. String bone = concat;
  397. int idx = skeleton->find_bone(bone);
  398. List<String> bone_path;
  399. while (idx != -1) {
  400. bone_path.push_front(skeleton->get_bone_name(idx));
  401. idx = skeleton->get_bone_parent(idx);
  402. }
  403. accum += ":";
  404. for (List<String>::Element *F = bone_path.front(); F; F = F->next()) {
  405. if (F != bone_path.front()) {
  406. accum += "/";
  407. }
  408. accum += F->get();
  409. if (!parenthood.has(accum)) {
  410. ti = filters->create_item(ti);
  411. parenthood[accum] = ti;
  412. ti->set_text(0, F->get());
  413. ti->set_selectable(0, false);
  414. ti->set_editable(0, false);
  415. ti->set_icon(0, get_icon("BoneAttachment", "EditorIcons"));
  416. } else {
  417. ti = parenthood[accum];
  418. }
  419. }
  420. ti->set_editable(0, true);
  421. ti->set_selectable(0, true);
  422. ti->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
  423. ti->set_text(0, concat);
  424. ti->set_checked(0, anode->is_path_filtered(path));
  425. ti->set_icon(0, get_icon("BoneAttachment", "EditorIcons"));
  426. ti->set_metadata(0, path);
  427. } else {
  428. //just a property
  429. ti = filters->create_item(ti);
  430. ti->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
  431. ti->set_text(0, concat);
  432. ti->set_editable(0, true);
  433. ti->set_selectable(0, true);
  434. ti->set_checked(0, anode->is_path_filtered(path));
  435. ti->set_metadata(0, path);
  436. }
  437. } else {
  438. if (ti) {
  439. //just a node, likely call or animation track
  440. ti->set_editable(0, true);
  441. ti->set_selectable(0, true);
  442. ti->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
  443. ti->set_checked(0, anode->is_path_filtered(path));
  444. ti->set_metadata(0, path);
  445. }
  446. }
  447. }
  448. updating = false;
  449. return true;
  450. }
  451. void AnimationNodeBlendTreeEditor::_edit_filters(const String &p_which) {
  452. Ref<AnimationNode> anode = blend_tree->get_node(p_which);
  453. ERR_FAIL_COND(!anode.is_valid());
  454. _filter_edit = anode;
  455. if (!_update_filters(anode))
  456. return;
  457. filter_dialog->popup_centered_minsize(Size2(500, 500) * EDSCALE);
  458. }
  459. void AnimationNodeBlendTreeEditor::_removed_from_graph() {
  460. if (is_visible()) {
  461. EditorNode::get_singleton()->edit_item(NULL);
  462. }
  463. }
  464. void AnimationNodeBlendTreeEditor::_notification(int p_what) {
  465. if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
  466. goto_parent->set_icon(get_icon("MoveUp", "EditorIcons"));
  467. error_panel->add_style_override("panel", get_stylebox("bg", "Tree"));
  468. error_label->add_color_override("font_color", get_color("error_color", "Editor"));
  469. }
  470. if (p_what == NOTIFICATION_PROCESS) {
  471. String error;
  472. if (!blend_tree->get_graph_player()) {
  473. error = TTR("BlendTree does not belong to an AnimationGraphPlayer node.");
  474. } else if (!blend_tree->get_graph_player()->is_active()) {
  475. error = TTR("AnimationGraphPlayer is inactive.\nActivate to enable playback, check node warnings if activation fails.");
  476. } else if (blend_tree->get_graph_player()->is_state_invalid()) {
  477. error = blend_tree->get_graph_player()->get_invalid_state_reason();
  478. }
  479. if (error != error_label->get_text()) {
  480. error_label->set_text(error);
  481. if (error != String()) {
  482. error_panel->show();
  483. } else {
  484. error_panel->hide();
  485. }
  486. }
  487. List<AnimationNodeBlendTree::NodeConnection> conns;
  488. blend_tree->get_node_connections(&conns);
  489. for (List<AnimationNodeBlendTree::NodeConnection>::Element *E = conns.front(); E; E = E->next()) {
  490. float activity = 0;
  491. if (blend_tree->get_graph_player() && !blend_tree->get_graph_player()->is_state_invalid()) {
  492. activity = blend_tree->get_connection_activity(E->get().input_node, E->get().input_index);
  493. }
  494. graph->set_connection_activity(E->get().output_node, 0, E->get().input_node, E->get().input_index, activity);
  495. }
  496. AnimationGraphPlayer *graph_player = blend_tree->get_graph_player();
  497. AnimationPlayer *player = NULL;
  498. if (graph_player->has_node(graph_player->get_animation_player())) {
  499. player = Object::cast_to<AnimationPlayer>(graph_player->get_node(graph_player->get_animation_player()));
  500. }
  501. if (player) {
  502. for (Map<StringName, ProgressBar *>::Element *E = animations.front(); E; E = E->next()) {
  503. Ref<AnimationNodeAnimation> an = blend_tree->get_node(E->key());
  504. if (an.is_valid()) {
  505. if (player->has_animation(an->get_animation())) {
  506. Ref<Animation> anim = player->get_animation(an->get_animation());
  507. if (anim.is_valid()) {
  508. E->get()->set_max(anim->get_length());
  509. E->get()->set_value(an->get_playback_time());
  510. }
  511. }
  512. }
  513. }
  514. }
  515. }
  516. }
  517. void AnimationNodeBlendTreeEditor::_scroll_changed(const Vector2 &p_scroll) {
  518. if (updating)
  519. return;
  520. updating = true;
  521. blend_tree->set_graph_offset(p_scroll / EDSCALE);
  522. updating = false;
  523. }
  524. void AnimationNodeBlendTreeEditor::_node_changed(ObjectID p_node) {
  525. AnimationNode *an = Object::cast_to<AnimationNode>(ObjectDB::get_instance(p_node));
  526. if (an && an->get_parent() == blend_tree) {
  527. _update_graph();
  528. }
  529. }
  530. void AnimationNodeBlendTreeEditor::_bind_methods() {
  531. ClassDB::bind_method("_update_graph", &AnimationNodeBlendTreeEditor::_update_graph);
  532. ClassDB::bind_method("_add_node", &AnimationNodeBlendTreeEditor::_add_node);
  533. ClassDB::bind_method("_node_dragged", &AnimationNodeBlendTreeEditor::_node_dragged);
  534. ClassDB::bind_method("_node_renamed", &AnimationNodeBlendTreeEditor::_node_renamed);
  535. ClassDB::bind_method("_node_renamed_focus_out", &AnimationNodeBlendTreeEditor::_node_renamed_focus_out);
  536. ClassDB::bind_method("_connection_request", &AnimationNodeBlendTreeEditor::_connection_request);
  537. ClassDB::bind_method("_disconnection_request", &AnimationNodeBlendTreeEditor::_disconnection_request);
  538. ClassDB::bind_method("_node_selected", &AnimationNodeBlendTreeEditor::_node_selected);
  539. ClassDB::bind_method("_open_in_editor", &AnimationNodeBlendTreeEditor::_open_in_editor);
  540. ClassDB::bind_method("_open_parent", &AnimationNodeBlendTreeEditor::_open_parent);
  541. ClassDB::bind_method("_scroll_changed", &AnimationNodeBlendTreeEditor::_scroll_changed);
  542. ClassDB::bind_method("_delete_request", &AnimationNodeBlendTreeEditor::_delete_request);
  543. ClassDB::bind_method("_edit_filters", &AnimationNodeBlendTreeEditor::_edit_filters);
  544. ClassDB::bind_method("_update_filters", &AnimationNodeBlendTreeEditor::_update_filters);
  545. ClassDB::bind_method("_filter_edited", &AnimationNodeBlendTreeEditor::_filter_edited);
  546. ClassDB::bind_method("_filter_toggled", &AnimationNodeBlendTreeEditor::_filter_toggled);
  547. ClassDB::bind_method("_oneshot_start", &AnimationNodeBlendTreeEditor::_oneshot_start);
  548. ClassDB::bind_method("_oneshot_stop", &AnimationNodeBlendTreeEditor::_oneshot_stop);
  549. ClassDB::bind_method("_node_changed", &AnimationNodeBlendTreeEditor::_node_changed);
  550. ClassDB::bind_method("_removed_from_graph", &AnimationNodeBlendTreeEditor::_removed_from_graph);
  551. ClassDB::bind_method("_anim_selected", &AnimationNodeBlendTreeEditor::_anim_selected);
  552. }
  553. AnimationNodeBlendTreeEditor *AnimationNodeBlendTreeEditor::singleton = NULL;
  554. void AnimationNodeBlendTreeEditor::_node_renamed(const String &p_text, Ref<AnimationNode> p_node) {
  555. String prev_name = blend_tree->get_node_name(p_node);
  556. ERR_FAIL_COND(prev_name == String());
  557. GraphNode *gn = Object::cast_to<GraphNode>(graph->get_node(prev_name));
  558. ERR_FAIL_COND(!gn);
  559. String new_name = p_text;
  560. ERR_FAIL_COND(new_name == "" || new_name.find(".") != -1 || new_name.find("/") != -1)
  561. ERR_FAIL_COND(new_name == prev_name);
  562. String base_name = new_name;
  563. int base = 1;
  564. String name = base_name;
  565. while (blend_tree->has_node(name)) {
  566. base++;
  567. name = base_name + " " + itos(base);
  568. }
  569. updating = true;
  570. undo_redo->create_action("Node Renamed");
  571. undo_redo->add_do_method(blend_tree.ptr(), "rename_node", prev_name, name);
  572. undo_redo->add_undo_method(blend_tree.ptr(), "rename_node", name, prev_name);
  573. undo_redo->add_do_method(this, "_update_graph");
  574. undo_redo->add_undo_method(this, "_update_graph");
  575. undo_redo->commit_action();
  576. updating = false;
  577. gn->set_name(new_name);
  578. gn->set_size(gn->get_minimum_size());
  579. }
  580. void AnimationNodeBlendTreeEditor::_node_renamed_focus_out(Node *le, Ref<AnimationNode> p_node) {
  581. _node_renamed(le->call("get_text"), p_node);
  582. }
  583. AnimationNodeBlendTreeEditor::AnimationNodeBlendTreeEditor() {
  584. singleton = this;
  585. updating = false;
  586. graph = memnew(GraphEdit);
  587. add_child(graph);
  588. graph->add_valid_right_disconnect_type(0);
  589. graph->add_valid_left_disconnect_type(0);
  590. graph->set_v_size_flags(SIZE_EXPAND_FILL);
  591. graph->connect("connection_request", this, "_connection_request", varray(), CONNECT_DEFERRED);
  592. graph->connect("disconnection_request", this, "_disconnection_request", varray(), CONNECT_DEFERRED);
  593. graph->connect("node_selected", this, "_node_selected");
  594. graph->connect("scroll_offset_changed", this, "_scroll_changed");
  595. VSeparator *vs = memnew(VSeparator);
  596. graph->get_zoom_hbox()->add_child(vs);
  597. graph->get_zoom_hbox()->move_child(vs, 0);
  598. add_node = memnew(MenuButton);
  599. graph->get_zoom_hbox()->add_child(add_node);
  600. add_node->set_text(TTR("Add Node.."));
  601. graph->get_zoom_hbox()->move_child(add_node, 0);
  602. add_node->get_popup()->connect("index_pressed", this, "_add_node");
  603. goto_parent = memnew(Button);
  604. graph->get_zoom_hbox()->add_child(goto_parent);
  605. graph->get_zoom_hbox()->move_child(goto_parent, 0);
  606. goto_parent->hide();
  607. goto_parent->connect("pressed", this, "_open_parent");
  608. add_options.push_back(AddOption("Animation", "AnimationNodeAnimation"));
  609. add_options.push_back(AddOption("OneShot", "AnimationNodeOneShot"));
  610. add_options.push_back(AddOption("Add", "AnimationNodeAdd"));
  611. add_options.push_back(AddOption("Blend2", "AnimationNodeBlend2"));
  612. add_options.push_back(AddOption("Blend3", "AnimationNodeBlend3"));
  613. add_options.push_back(AddOption("Seek", "AnimationNodeTimeSeek"));
  614. add_options.push_back(AddOption("TimeScale", "AnimationNodeTimeScale"));
  615. add_options.push_back(AddOption("Transition", "AnimationNodeTransition"));
  616. add_options.push_back(AddOption("BlendTree", "AnimationNodeBlendTree"));
  617. add_options.push_back(AddOption("BlendSpace", "AnimationNodeBlendSpace"));
  618. _update_options_menu();
  619. error_panel = memnew(PanelContainer);
  620. add_child(error_panel);
  621. error_label = memnew(Label);
  622. error_panel->add_child(error_label);
  623. error_label->set_text("eh");
  624. filter_dialog = memnew(AcceptDialog);
  625. add_child(filter_dialog);
  626. filter_dialog->set_title(TTR("Edit Filtered Tracks:"));
  627. VBoxContainer *filter_vbox = memnew(VBoxContainer);
  628. filter_dialog->add_child(filter_vbox);
  629. filter_enabled = memnew(CheckBox);
  630. filter_enabled->set_text(TTR("Enable filtering"));
  631. filter_enabled->connect("pressed", this, "_filter_toggled");
  632. filter_vbox->add_child(filter_enabled);
  633. filters = memnew(Tree);
  634. filter_vbox->add_child(filters);
  635. filters->set_v_size_flags(SIZE_EXPAND_FILL);
  636. filters->set_hide_root(true);
  637. filters->connect("item_edited", this, "_filter_edited");
  638. undo_redo = EditorNode::get_singleton()->get_undo_redo();
  639. }
  640. void AnimationNodeBlendTreeEditorPlugin::edit(Object *p_object) {
  641. anim_tree_editor->edit(Object::cast_to<AnimationNodeBlendTree>(p_object));
  642. }
  643. bool AnimationNodeBlendTreeEditorPlugin::handles(Object *p_object) const {
  644. return p_object->is_class("AnimationNodeBlendTree");
  645. }
  646. void AnimationNodeBlendTreeEditorPlugin::make_visible(bool p_visible) {
  647. if (p_visible) {
  648. //editor->hide_animation_player_editors();
  649. //editor->animation_panel_make_visible(true);
  650. button->show();
  651. editor->make_bottom_panel_item_visible(anim_tree_editor);
  652. anim_tree_editor->set_process(true);
  653. } else {
  654. if (anim_tree_editor->is_visible_in_tree())
  655. editor->hide_bottom_panel();
  656. button->hide();
  657. anim_tree_editor->set_process(false);
  658. }
  659. }
  660. AnimationNodeBlendTreeEditorPlugin::AnimationNodeBlendTreeEditorPlugin(EditorNode *p_node) {
  661. editor = p_node;
  662. anim_tree_editor = memnew(AnimationNodeBlendTreeEditor);
  663. anim_tree_editor->set_custom_minimum_size(Size2(0, 300));
  664. button = editor->add_bottom_panel_item(TTR("BlendTree"), anim_tree_editor);
  665. button->hide();
  666. }
  667. AnimationNodeBlendTreeEditorPlugin::~AnimationNodeBlendTreeEditorPlugin() {
  668. }