animation_blend_space_2d_editor.cpp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071
  1. /*************************************************************************/
  2. /* animation_blend_space_2d_editor.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /*************************************************************************/
  30. #include "animation_blend_space_2d_editor.h"
  31. #include "core/io/resource_loader.h"
  32. #include "core/math/delaunay.h"
  33. #include "core/os/input.h"
  34. #include "core/os/keyboard.h"
  35. #include "core/project_settings.h"
  36. #include "scene/animation/animation_blend_tree.h"
  37. #include "scene/animation/animation_player.h"
  38. #include "scene/gui/menu_button.h"
  39. #include "scene/gui/panel.h"
  40. #include "scene/main/viewport.h"
  41. bool AnimationNodeBlendSpace2DEditor::can_edit(const Ref<AnimationNode> &p_node) {
  42. Ref<AnimationNodeBlendSpace2D> bs2d = p_node;
  43. return bs2d.is_valid();
  44. }
  45. void AnimationNodeBlendSpace2DEditor::_blend_space_changed() {
  46. blend_space_draw->update();
  47. }
  48. void AnimationNodeBlendSpace2DEditor::edit(const Ref<AnimationNode> &p_node) {
  49. if (blend_space.is_valid()) {
  50. blend_space->disconnect("triangles_updated", this, "_blend_space_changed");
  51. }
  52. blend_space = p_node;
  53. if (!blend_space.is_null()) {
  54. blend_space->connect("triangles_updated", this, "_blend_space_changed");
  55. _update_space();
  56. }
  57. }
  58. StringName AnimationNodeBlendSpace2DEditor::get_blend_position_path() const {
  59. StringName path = AnimationTreeEditor::get_singleton()->get_base_path() + "blend_position";
  60. return path;
  61. }
  62. void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEvent> &p_event) {
  63. Ref<InputEventKey> k = p_event;
  64. if (tool_select->is_pressed() && k.is_valid() && k->is_pressed() && k->get_scancode() == KEY_DELETE && !k->is_echo()) {
  65. if (selected_point != -1 || selected_triangle != -1) {
  66. _erase_selected();
  67. accept_event();
  68. }
  69. }
  70. Ref<InputEventMouseButton> mb = p_event;
  71. if (mb.is_valid() && mb->is_pressed() && ((tool_select->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) || (mb->get_button_index() == BUTTON_LEFT && tool_create->is_pressed()))) {
  72. menu->clear();
  73. animations_menu->clear();
  74. animations_to_add.clear();
  75. List<StringName> classes;
  76. classes.sort_custom<StringName::AlphCompare>();
  77. ClassDB::get_inheriters_from_class("AnimationRootNode", &classes);
  78. menu->add_submenu_item(TTR("Add Animation"), "animations");
  79. AnimationTree *gp = AnimationTreeEditor::get_singleton()->get_tree();
  80. ERR_FAIL_COND(!gp);
  81. if (gp && gp->has_node(gp->get_animation_player())) {
  82. AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(gp->get_node(gp->get_animation_player()));
  83. if (ap) {
  84. List<StringName> names;
  85. ap->get_animation_list(&names);
  86. for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
  87. animations_menu->add_icon_item(get_icon("Animation", "EditorIcons"), E->get());
  88. animations_to_add.push_back(E->get());
  89. }
  90. }
  91. }
  92. for (List<StringName>::Element *E = classes.front(); E; E = E->next()) {
  93. String name = String(E->get()).replace_first("AnimationNode", "");
  94. if (name == "Animation")
  95. continue; // nope
  96. int idx = menu->get_item_count();
  97. menu->add_item(vformat("Add %s", name), idx);
  98. menu->set_item_metadata(idx, E->get());
  99. }
  100. Ref<AnimationNode> clipb = EditorSettings::get_singleton()->get_resource_clipboard();
  101. if (clipb.is_valid()) {
  102. menu->add_separator();
  103. menu->add_item(TTR("Paste"), MENU_PASTE);
  104. }
  105. menu->add_separator();
  106. menu->add_item(TTR("Load..."), MENU_LOAD_FILE);
  107. menu->set_global_position(blend_space_draw->get_global_transform().xform(mb->get_position()));
  108. menu->popup();
  109. add_point_pos = (mb->get_position() / blend_space_draw->get_size());
  110. add_point_pos.y = 1.0 - add_point_pos.y;
  111. add_point_pos *= (blend_space->get_max_space() - blend_space->get_min_space());
  112. add_point_pos += blend_space->get_min_space();
  113. if (snap->is_pressed()) {
  114. add_point_pos.x = Math::stepify(add_point_pos.x, blend_space->get_snap().x);
  115. add_point_pos.y = Math::stepify(add_point_pos.y, blend_space->get_snap().y);
  116. }
  117. }
  118. if (mb.is_valid() && mb->is_pressed() && tool_select->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
  119. blend_space_draw->update(); //update anyway
  120. //try to see if a point can be selected
  121. selected_point = -1;
  122. selected_triangle = -1;
  123. _update_tool_erase();
  124. for (int i = 0; i < points.size(); i++) {
  125. if (points[i].distance_to(mb->get_position()) < 10 * EDSCALE) {
  126. selected_point = i;
  127. Ref<AnimationNode> node = blend_space->get_blend_point_node(i);
  128. EditorNode::get_singleton()->push_item(node.ptr(), "", true);
  129. dragging_selected_attempt = true;
  130. drag_from = mb->get_position();
  131. _update_tool_erase();
  132. _update_edited_point_pos();
  133. return;
  134. }
  135. }
  136. //then try to see if a triangle can be selected
  137. if (!blend_space->get_auto_triangles()) { //if autotriangles use, disable this
  138. for (int i = 0; i < blend_space->get_triangle_count(); i++) {
  139. Vector<Vector2> triangle;
  140. for (int j = 0; j < 3; j++) {
  141. int idx = blend_space->get_triangle_point(i, j);
  142. ERR_FAIL_INDEX(idx, points.size());
  143. triangle.push_back(points[idx]);
  144. }
  145. if (Geometry::is_point_in_triangle(mb->get_position(), triangle[0], triangle[1], triangle[2])) {
  146. selected_triangle = i;
  147. _update_tool_erase();
  148. return;
  149. }
  150. }
  151. }
  152. }
  153. if (mb.is_valid() && mb->is_pressed() && tool_triangle->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
  154. blend_space_draw->update(); //update anyway
  155. //try to see if a point can be selected
  156. selected_point = -1;
  157. for (int i = 0; i < points.size(); i++) {
  158. if (making_triangle.find(i) != -1)
  159. continue;
  160. if (points[i].distance_to(mb->get_position()) < 10 * EDSCALE) {
  161. making_triangle.push_back(i);
  162. if (making_triangle.size() == 3) {
  163. //add triangle!
  164. if (blend_space->has_triangle(making_triangle[0], making_triangle[1], making_triangle[2])) {
  165. making_triangle.clear();
  166. EditorNode::get_singleton()->show_warning(TTR("Triangle already exists"));
  167. return;
  168. }
  169. updating = true;
  170. undo_redo->create_action(TTR("Add Triangle"));
  171. undo_redo->add_do_method(blend_space.ptr(), "add_triangle", making_triangle[0], making_triangle[1], making_triangle[2]);
  172. undo_redo->add_undo_method(blend_space.ptr(), "remove_triangle", blend_space->get_triangle_count());
  173. undo_redo->add_do_method(this, "_update_space");
  174. undo_redo->add_undo_method(this, "_update_space");
  175. undo_redo->commit_action();
  176. updating = false;
  177. making_triangle.clear();
  178. }
  179. return;
  180. }
  181. }
  182. }
  183. if (mb.is_valid() && !mb->is_pressed() && dragging_selected_attempt && mb->get_button_index() == BUTTON_LEFT) {
  184. if (dragging_selected) {
  185. //move
  186. Vector2 point = blend_space->get_blend_point_position(selected_point);
  187. point += drag_ofs;
  188. if (snap->is_pressed()) {
  189. point.x = Math::stepify(point.x, blend_space->get_snap().x);
  190. point.y = Math::stepify(point.y, blend_space->get_snap().y);
  191. }
  192. updating = true;
  193. undo_redo->create_action(TTR("Move Node Point"));
  194. undo_redo->add_do_method(blend_space.ptr(), "set_blend_point_position", selected_point, point);
  195. undo_redo->add_undo_method(blend_space.ptr(), "set_blend_point_position", selected_point, blend_space->get_blend_point_position(selected_point));
  196. undo_redo->add_do_method(this, "_update_space");
  197. undo_redo->add_undo_method(this, "_update_space");
  198. undo_redo->add_do_method(this, "_update_edited_point_pos");
  199. undo_redo->add_undo_method(this, "_update_edited_point_pos");
  200. undo_redo->commit_action();
  201. updating = false;
  202. _update_edited_point_pos();
  203. }
  204. dragging_selected_attempt = false;
  205. dragging_selected = false;
  206. blend_space_draw->update();
  207. }
  208. if (mb.is_valid() && mb->is_pressed() && tool_blend->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
  209. Vector2 blend_pos = (mb->get_position() / blend_space_draw->get_size());
  210. blend_pos.y = 1.0 - blend_pos.y;
  211. blend_pos *= (blend_space->get_max_space() - blend_space->get_min_space());
  212. blend_pos += blend_space->get_min_space();
  213. AnimationTreeEditor::get_singleton()->get_tree()->set(get_blend_position_path(), blend_pos);
  214. blend_space_draw->update();
  215. }
  216. Ref<InputEventMouseMotion> mm = p_event;
  217. if (mm.is_valid() && !blend_space_draw->has_focus()) {
  218. blend_space_draw->grab_focus();
  219. blend_space_draw->update();
  220. }
  221. if (mm.is_valid() && dragging_selected_attempt) {
  222. dragging_selected = true;
  223. drag_ofs = ((mm->get_position() - drag_from) / blend_space_draw->get_size()) * (blend_space->get_max_space() - blend_space->get_min_space()) * Vector2(1, -1);
  224. blend_space_draw->update();
  225. _update_edited_point_pos();
  226. }
  227. if (mm.is_valid() && tool_triangle->is_pressed() && making_triangle.size()) {
  228. blend_space_draw->update();
  229. }
  230. if (mm.is_valid() && !tool_triangle->is_pressed() && making_triangle.size()) {
  231. making_triangle.clear();
  232. blend_space_draw->update();
  233. }
  234. if (mm.is_valid() && tool_blend->is_pressed() && mm->get_button_mask() & BUTTON_MASK_LEFT) {
  235. Vector2 blend_pos = (mm->get_position() / blend_space_draw->get_size());
  236. blend_pos.y = 1.0 - blend_pos.y;
  237. blend_pos *= (blend_space->get_max_space() - blend_space->get_min_space());
  238. blend_pos += blend_space->get_min_space();
  239. AnimationTreeEditor::get_singleton()->get_tree()->set(get_blend_position_path(), blend_pos);
  240. blend_space_draw->update();
  241. }
  242. }
  243. void AnimationNodeBlendSpace2DEditor::_file_opened(const String &p_file) {
  244. file_loaded = ResourceLoader::load(p_file);
  245. if (file_loaded.is_valid()) {
  246. _add_menu_type(MENU_LOAD_FILE_CONFIRM);
  247. }
  248. }
  249. void AnimationNodeBlendSpace2DEditor::_add_menu_type(int p_index) {
  250. Ref<AnimationRootNode> node;
  251. if (p_index == MENU_LOAD_FILE) {
  252. open_file->clear_filters();
  253. List<String> filters;
  254. ResourceLoader::get_recognized_extensions_for_type("AnimationRootNode", &filters);
  255. for (List<String>::Element *E = filters.front(); E; E = E->next()) {
  256. open_file->add_filter("*." + E->get());
  257. }
  258. open_file->popup_centered_ratio();
  259. return;
  260. } else if (p_index == MENU_LOAD_FILE_CONFIRM) {
  261. node = file_loaded;
  262. file_loaded.unref();
  263. } else if (p_index == MENU_PASTE) {
  264. node = EditorSettings::get_singleton()->get_resource_clipboard();
  265. } else {
  266. String type = menu->get_item_metadata(p_index);
  267. Object *obj = ClassDB::instance(type);
  268. ERR_FAIL_COND(!obj);
  269. AnimationNode *an = Object::cast_to<AnimationNode>(obj);
  270. ERR_FAIL_COND(!an);
  271. node = Ref<AnimationNode>(an);
  272. }
  273. if (!node.is_valid()) {
  274. EditorNode::get_singleton()->show_warning(TTR("This type of node can't be used. Only root nodes are allowed."));
  275. return;
  276. }
  277. updating = true;
  278. undo_redo->create_action(TTR("Add Node Point"));
  279. undo_redo->add_do_method(blend_space.ptr(), "add_blend_point", node, add_point_pos);
  280. undo_redo->add_undo_method(blend_space.ptr(), "remove_blend_point", blend_space->get_blend_point_count());
  281. undo_redo->add_do_method(this, "_update_space");
  282. undo_redo->add_undo_method(this, "_update_space");
  283. undo_redo->commit_action();
  284. updating = false;
  285. blend_space_draw->update();
  286. }
  287. void AnimationNodeBlendSpace2DEditor::_add_animation_type(int p_index) {
  288. Ref<AnimationNodeAnimation> anim;
  289. anim.instance();
  290. anim->set_animation(animations_to_add[p_index]);
  291. updating = true;
  292. undo_redo->create_action(TTR("Add Animation Point"));
  293. undo_redo->add_do_method(blend_space.ptr(), "add_blend_point", anim, add_point_pos);
  294. undo_redo->add_undo_method(blend_space.ptr(), "remove_blend_point", blend_space->get_blend_point_count());
  295. undo_redo->add_do_method(this, "_update_space");
  296. undo_redo->add_undo_method(this, "_update_space");
  297. undo_redo->commit_action();
  298. updating = false;
  299. blend_space_draw->update();
  300. }
  301. void AnimationNodeBlendSpace2DEditor::_update_tool_erase() {
  302. tool_erase->set_disabled(!(selected_point >= 0 && selected_point < blend_space->get_blend_point_count()) && !(selected_triangle >= 0 && selected_triangle < blend_space->get_triangle_count()));
  303. if (selected_point >= 0 && selected_point < blend_space->get_blend_point_count()) {
  304. Ref<AnimationNode> an = blend_space->get_blend_point_node(selected_point);
  305. if (AnimationTreeEditor::get_singleton()->can_edit(an)) {
  306. open_editor->show();
  307. } else {
  308. open_editor->hide();
  309. }
  310. edit_hb->show();
  311. } else {
  312. edit_hb->hide();
  313. }
  314. }
  315. void AnimationNodeBlendSpace2DEditor::_tool_switch(int p_tool) {
  316. making_triangle.clear();
  317. if (p_tool == 2) {
  318. Vector<Vector2> points;
  319. for (int i = 0; i < blend_space->get_blend_point_count(); i++) {
  320. points.push_back(blend_space->get_blend_point_position(i));
  321. }
  322. Vector<Delaunay2D::Triangle> tr = Delaunay2D::triangulate(points);
  323. for (int i = 0; i < tr.size(); i++) {
  324. blend_space->add_triangle(tr[i].points[0], tr[i].points[1], tr[i].points[2]);
  325. }
  326. }
  327. if (p_tool == 0) {
  328. tool_erase->show();
  329. tool_erase_sep->show();
  330. } else {
  331. tool_erase->hide();
  332. tool_erase_sep->hide();
  333. }
  334. _update_tool_erase();
  335. blend_space_draw->update();
  336. }
  337. void AnimationNodeBlendSpace2DEditor::_blend_space_draw() {
  338. Color linecolor = get_color("font_color", "Label");
  339. Color linecolor_soft = linecolor;
  340. linecolor_soft.a *= 0.5;
  341. Ref<Font> font = get_font("font", "Label");
  342. Ref<Texture> icon = get_icon("KeyValue", "EditorIcons");
  343. Ref<Texture> icon_selected = get_icon("KeySelected", "EditorIcons");
  344. Size2 s = blend_space_draw->get_size();
  345. if (blend_space_draw->has_focus()) {
  346. Color color = get_color("accent_color", "Editor");
  347. blend_space_draw->draw_rect(Rect2(Point2(), s), color, false);
  348. }
  349. blend_space_draw->draw_line(Point2(1, 0), Point2(1, s.height - 1), linecolor);
  350. blend_space_draw->draw_line(Point2(1, s.height - 1), Point2(s.width - 1, s.height - 1), linecolor);
  351. blend_space_draw->draw_line(Point2(0, 0), Point2(5 * EDSCALE, 0), linecolor);
  352. if (blend_space->get_min_space().y < 0) {
  353. int y = (blend_space->get_max_space().y / (blend_space->get_max_space().y - blend_space->get_min_space().y)) * s.height;
  354. blend_space_draw->draw_line(Point2(0, y), Point2(5 * EDSCALE, y), linecolor);
  355. blend_space_draw->draw_string(font, Point2(2 * EDSCALE, y - font->get_height() + font->get_ascent()), "0", linecolor);
  356. blend_space_draw->draw_line(Point2(5 * EDSCALE, y), Point2(s.width, y), linecolor_soft);
  357. }
  358. if (blend_space->get_min_space().x < 0) {
  359. int x = (-blend_space->get_min_space().x / (blend_space->get_max_space().x - blend_space->get_min_space().x)) * s.width;
  360. blend_space_draw->draw_line(Point2(x, s.height - 1), Point2(x, s.height - 5 * EDSCALE), linecolor);
  361. blend_space_draw->draw_string(font, Point2(x + 2 * EDSCALE, s.height - 2 * EDSCALE - font->get_height() + font->get_ascent()), "0", linecolor);
  362. blend_space_draw->draw_line(Point2(x, s.height - 5 * EDSCALE), Point2(x, 0), linecolor_soft);
  363. }
  364. if (snap->is_pressed()) {
  365. linecolor_soft.a = linecolor.a * 0.1;
  366. if (blend_space->get_snap().x > 0) {
  367. int prev_idx = 0;
  368. for (int i = 0; i < s.x; i++) {
  369. float v = blend_space->get_min_space().x + i * (blend_space->get_max_space().x - blend_space->get_min_space().x) / s.x;
  370. int idx = int(v / blend_space->get_snap().x);
  371. if (i > 0 && prev_idx != idx) {
  372. blend_space_draw->draw_line(Point2(i, 0), Point2(i, s.height), linecolor_soft);
  373. }
  374. prev_idx = idx;
  375. }
  376. }
  377. if (blend_space->get_snap().y > 0) {
  378. int prev_idx = 0;
  379. for (int i = 0; i < s.y; i++) {
  380. float v = blend_space->get_max_space().y - i * (blend_space->get_max_space().y - blend_space->get_min_space().y) / s.y;
  381. int idx = int(v / blend_space->get_snap().y);
  382. if (i > 0 && prev_idx != idx) {
  383. blend_space_draw->draw_line(Point2(0, i), Point2(s.width, i), linecolor_soft);
  384. }
  385. prev_idx = idx;
  386. }
  387. }
  388. }
  389. //triangles first
  390. for (int i = 0; i < blend_space->get_triangle_count(); i++) {
  391. Vector<Vector2> points;
  392. points.resize(3);
  393. for (int j = 0; j < 3; j++) {
  394. int point_idx = blend_space->get_triangle_point(i, j);
  395. Vector2 point = blend_space->get_blend_point_position(point_idx);
  396. if (dragging_selected && selected_point == point_idx) {
  397. point += drag_ofs;
  398. if (snap->is_pressed()) {
  399. point.x = Math::stepify(point.x, blend_space->get_snap().x);
  400. point.y = Math::stepify(point.y, blend_space->get_snap().y);
  401. }
  402. }
  403. point = (point - blend_space->get_min_space()) / (blend_space->get_max_space() - blend_space->get_min_space());
  404. point *= s;
  405. point.y = s.height - point.y;
  406. points.write[j] = point;
  407. }
  408. for (int j = 0; j < 3; j++) {
  409. blend_space_draw->draw_line(points[j], points[(j + 1) % 3], linecolor, 1, true);
  410. }
  411. Color color;
  412. if (i == selected_triangle) {
  413. color = get_color("accent_color", "Editor");
  414. color.a *= 0.5;
  415. } else {
  416. color = linecolor;
  417. color.a *= 0.2;
  418. }
  419. Vector<Color> colors;
  420. colors.push_back(color);
  421. colors.push_back(color);
  422. colors.push_back(color);
  423. blend_space_draw->draw_primitive(points, colors, Vector<Vector2>());
  424. }
  425. points.clear();
  426. for (int i = 0; i < blend_space->get_blend_point_count(); i++) {
  427. Vector2 point = blend_space->get_blend_point_position(i);
  428. if (dragging_selected && selected_point == i) {
  429. point += drag_ofs;
  430. if (snap->is_pressed()) {
  431. point.x = Math::stepify(point.x, blend_space->get_snap().x);
  432. point.y = Math::stepify(point.y, blend_space->get_snap().y);
  433. }
  434. }
  435. point = (point - blend_space->get_min_space()) / (blend_space->get_max_space() - blend_space->get_min_space());
  436. point *= s;
  437. point.y = s.height - point.y;
  438. points.push_back(point);
  439. point -= (icon->get_size() / 2);
  440. point = point.floor();
  441. if (i == selected_point) {
  442. blend_space_draw->draw_texture(icon_selected, point);
  443. } else {
  444. blend_space_draw->draw_texture(icon, point);
  445. }
  446. }
  447. if (making_triangle.size()) {
  448. Vector<Vector2> points;
  449. for (int i = 0; i < making_triangle.size(); i++) {
  450. Vector2 point = blend_space->get_blend_point_position(making_triangle[i]);
  451. point = (point - blend_space->get_min_space()) / (blend_space->get_max_space() - blend_space->get_min_space());
  452. point *= s;
  453. point.y = s.height - point.y;
  454. points.push_back(point);
  455. }
  456. for (int i = 0; i < points.size() - 1; i++) {
  457. blend_space_draw->draw_line(points[i], points[i + 1], linecolor, 2, true);
  458. }
  459. blend_space_draw->draw_line(points[points.size() - 1], blend_space_draw->get_local_mouse_position(), linecolor, 2, true);
  460. }
  461. ///draw cursor position
  462. {
  463. Color color;
  464. if (tool_blend->is_pressed()) {
  465. color = get_color("accent_color", "Editor");
  466. } else {
  467. color = linecolor;
  468. color.a *= 0.5;
  469. }
  470. Vector2 blend_pos = AnimationTreeEditor::get_singleton()->get_tree()->get(get_blend_position_path());
  471. Vector2 point = blend_pos;
  472. point = (point - blend_space->get_min_space()) / (blend_space->get_max_space() - blend_space->get_min_space());
  473. point *= s;
  474. point.y = s.height - point.y;
  475. if (blend_space->get_triangle_count()) {
  476. Vector2 closest = blend_space->get_closest_point(blend_pos);
  477. closest = (closest - blend_space->get_min_space()) / (blend_space->get_max_space() - blend_space->get_min_space());
  478. closest *= s;
  479. closest.y = s.height - closest.y;
  480. Color lcol = color;
  481. lcol.a *= 0.4;
  482. blend_space_draw->draw_line(point, closest, lcol, 2);
  483. }
  484. float mind = 5 * EDSCALE;
  485. float maxd = 15 * EDSCALE;
  486. blend_space_draw->draw_line(point + Vector2(mind, 0), point + Vector2(maxd, 0), color, 2);
  487. blend_space_draw->draw_line(point + Vector2(-mind, 0), point + Vector2(-maxd, 0), color, 2);
  488. blend_space_draw->draw_line(point + Vector2(0, mind), point + Vector2(0, maxd), color, 2);
  489. blend_space_draw->draw_line(point + Vector2(0, -mind), point + Vector2(0, -maxd), color, 2);
  490. }
  491. }
  492. void AnimationNodeBlendSpace2DEditor::_snap_toggled() {
  493. blend_space_draw->update();
  494. }
  495. void AnimationNodeBlendSpace2DEditor::_update_space() {
  496. if (updating)
  497. return;
  498. updating = true;
  499. if (blend_space->get_auto_triangles()) {
  500. tool_triangle->hide();
  501. } else {
  502. tool_triangle->show();
  503. }
  504. auto_triangles->set_pressed(blend_space->get_auto_triangles());
  505. interpolation->select(blend_space->get_blend_mode());
  506. max_x_value->set_value(blend_space->get_max_space().x);
  507. max_y_value->set_value(blend_space->get_max_space().y);
  508. min_x_value->set_value(blend_space->get_min_space().x);
  509. min_y_value->set_value(blend_space->get_min_space().y);
  510. label_x->set_text(blend_space->get_x_label());
  511. label_y->set_text(blend_space->get_y_label());
  512. snap_x->set_value(blend_space->get_snap().x);
  513. snap_y->set_value(blend_space->get_snap().y);
  514. blend_space_draw->update();
  515. updating = false;
  516. }
  517. void AnimationNodeBlendSpace2DEditor::_config_changed(double) {
  518. if (updating)
  519. return;
  520. updating = true;
  521. undo_redo->create_action(TTR("Change BlendSpace2D Limits"));
  522. undo_redo->add_do_method(blend_space.ptr(), "set_max_space", Vector2(max_x_value->get_value(), max_y_value->get_value()));
  523. undo_redo->add_undo_method(blend_space.ptr(), "set_max_space", blend_space->get_max_space());
  524. undo_redo->add_do_method(blend_space.ptr(), "set_min_space", Vector2(min_x_value->get_value(), min_y_value->get_value()));
  525. undo_redo->add_undo_method(blend_space.ptr(), "set_min_space", blend_space->get_min_space());
  526. undo_redo->add_do_method(blend_space.ptr(), "set_snap", Vector2(snap_x->get_value(), snap_y->get_value()));
  527. undo_redo->add_undo_method(blend_space.ptr(), "set_snap", blend_space->get_snap());
  528. undo_redo->add_do_method(blend_space.ptr(), "set_blend_mode", interpolation->get_selected());
  529. undo_redo->add_undo_method(blend_space.ptr(), "set_blend_mode", blend_space->get_blend_mode());
  530. undo_redo->add_do_method(this, "_update_space");
  531. undo_redo->add_undo_method(this, "_update_space");
  532. undo_redo->commit_action();
  533. updating = false;
  534. blend_space_draw->update();
  535. }
  536. void AnimationNodeBlendSpace2DEditor::_labels_changed(String) {
  537. if (updating)
  538. return;
  539. updating = true;
  540. undo_redo->create_action(TTR("Change BlendSpace2D Labels"), UndoRedo::MERGE_ENDS);
  541. undo_redo->add_do_method(blend_space.ptr(), "set_x_label", label_x->get_text());
  542. undo_redo->add_undo_method(blend_space.ptr(), "set_x_label", blend_space->get_x_label());
  543. undo_redo->add_do_method(blend_space.ptr(), "set_y_label", label_y->get_text());
  544. undo_redo->add_undo_method(blend_space.ptr(), "set_y_label", blend_space->get_y_label());
  545. undo_redo->add_do_method(this, "_update_space");
  546. undo_redo->add_undo_method(this, "_update_space");
  547. undo_redo->commit_action();
  548. updating = false;
  549. }
  550. void AnimationNodeBlendSpace2DEditor::_erase_selected() {
  551. if (selected_point != -1) {
  552. updating = true;
  553. undo_redo->create_action(TTR("Remove BlendSpace2D Point"));
  554. undo_redo->add_do_method(blend_space.ptr(), "remove_blend_point", selected_point);
  555. undo_redo->add_undo_method(blend_space.ptr(), "add_blend_point", blend_space->get_blend_point_node(selected_point), blend_space->get_blend_point_position(selected_point), selected_point);
  556. //restore triangles using this point
  557. for (int i = 0; i < blend_space->get_triangle_count(); i++) {
  558. for (int j = 0; j < 3; j++) {
  559. if (blend_space->get_triangle_point(i, j) == selected_point) {
  560. undo_redo->add_undo_method(blend_space.ptr(), "add_triangle", blend_space->get_triangle_point(i, 0), blend_space->get_triangle_point(i, 1), blend_space->get_triangle_point(i, 2), i);
  561. break;
  562. }
  563. }
  564. }
  565. undo_redo->add_do_method(this, "_update_space");
  566. undo_redo->add_undo_method(this, "_update_space");
  567. undo_redo->commit_action();
  568. updating = false;
  569. blend_space_draw->update();
  570. } else if (selected_triangle != -1) {
  571. updating = true;
  572. undo_redo->create_action(TTR("Remove BlendSpace2D Triangle"));
  573. undo_redo->add_do_method(blend_space.ptr(), "remove_triangle", selected_triangle);
  574. undo_redo->add_undo_method(blend_space.ptr(), "add_triangle", blend_space->get_triangle_point(selected_triangle, 0), blend_space->get_triangle_point(selected_triangle, 1), blend_space->get_triangle_point(selected_triangle, 2), selected_triangle);
  575. undo_redo->add_do_method(this, "_update_space");
  576. undo_redo->add_undo_method(this, "_update_space");
  577. undo_redo->commit_action();
  578. updating = false;
  579. blend_space_draw->update();
  580. }
  581. }
  582. void AnimationNodeBlendSpace2DEditor::_update_edited_point_pos() {
  583. if (updating)
  584. return;
  585. if (selected_point >= 0 && selected_point < blend_space->get_blend_point_count()) {
  586. Vector2 pos = blend_space->get_blend_point_position(selected_point);
  587. if (dragging_selected) {
  588. pos += drag_ofs;
  589. if (snap->is_pressed()) {
  590. pos.x = Math::stepify(pos.x, blend_space->get_snap().x);
  591. pos.y = Math::stepify(pos.y, blend_space->get_snap().y);
  592. }
  593. }
  594. updating = true;
  595. edit_x->set_value(pos.x);
  596. edit_y->set_value(pos.y);
  597. updating = false;
  598. }
  599. }
  600. void AnimationNodeBlendSpace2DEditor::_edit_point_pos(double) {
  601. if (updating)
  602. return;
  603. updating = true;
  604. undo_redo->create_action(TTR("Move Node Point"));
  605. undo_redo->add_do_method(blend_space.ptr(), "set_blend_point_position", selected_point, Vector2(edit_x->get_value(), edit_y->get_value()));
  606. undo_redo->add_undo_method(blend_space.ptr(), "set_blend_point_position", selected_point, blend_space->get_blend_point_position(selected_point));
  607. undo_redo->add_do_method(this, "_update_space");
  608. undo_redo->add_undo_method(this, "_update_space");
  609. undo_redo->add_do_method(this, "_update_edited_point_pos");
  610. undo_redo->add_undo_method(this, "_update_edited_point_pos");
  611. undo_redo->commit_action();
  612. updating = false;
  613. blend_space_draw->update();
  614. }
  615. void AnimationNodeBlendSpace2DEditor::_notification(int p_what) {
  616. if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
  617. error_panel->add_style_override("panel", get_stylebox("bg", "Tree"));
  618. error_label->add_color_override("font_color", get_color("error_color", "Editor"));
  619. panel->add_style_override("panel", get_stylebox("bg", "Tree"));
  620. tool_blend->set_icon(get_icon("EditPivot", "EditorIcons"));
  621. tool_select->set_icon(get_icon("ToolSelect", "EditorIcons"));
  622. tool_create->set_icon(get_icon("EditKey", "EditorIcons"));
  623. tool_triangle->set_icon(get_icon("ToolTriangle", "EditorIcons"));
  624. tool_erase->set_icon(get_icon("Remove", "EditorIcons"));
  625. snap->set_icon(get_icon("SnapGrid", "EditorIcons"));
  626. open_editor->set_icon(get_icon("Edit", "EditorIcons"));
  627. auto_triangles->set_icon(get_icon("AutoTriangle", "EditorIcons"));
  628. interpolation->clear();
  629. interpolation->add_icon_item(get_icon("TrackContinuous", "EditorIcons"), "", 0);
  630. interpolation->add_icon_item(get_icon("TrackDiscrete", "EditorIcons"), "", 1);
  631. interpolation->add_icon_item(get_icon("TrackCapture", "EditorIcons"), "", 2);
  632. }
  633. if (p_what == NOTIFICATION_PROCESS) {
  634. String error;
  635. if (!AnimationTreeEditor::get_singleton()->get_tree()) {
  636. error = TTR("BlendSpace2D does not belong to an AnimationTree node.");
  637. } else if (!AnimationTreeEditor::get_singleton()->get_tree()->is_active()) {
  638. error = TTR("AnimationTree is inactive.\nActivate to enable playback, check node warnings if activation fails.");
  639. } else if (AnimationTreeEditor::get_singleton()->get_tree()->is_state_invalid()) {
  640. error = AnimationTreeEditor::get_singleton()->get_tree()->get_invalid_state_reason();
  641. } else if (blend_space->get_triangle_count() == 0) {
  642. error = TTR("No triangles exist, so no blending can take place.");
  643. }
  644. if (error != error_label->get_text()) {
  645. error_label->set_text(error);
  646. if (error != String()) {
  647. error_panel->show();
  648. } else {
  649. error_panel->hide();
  650. }
  651. }
  652. }
  653. if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
  654. set_process(is_visible_in_tree());
  655. }
  656. }
  657. void AnimationNodeBlendSpace2DEditor::_open_editor() {
  658. if (selected_point >= 0 && selected_point < blend_space->get_blend_point_count()) {
  659. Ref<AnimationNode> an = blend_space->get_blend_point_node(selected_point);
  660. ERR_FAIL_COND(an.is_null());
  661. AnimationTreeEditor::get_singleton()->enter_editor(itos(selected_point));
  662. }
  663. }
  664. void AnimationNodeBlendSpace2DEditor::_removed_from_graph() {
  665. EditorNode::get_singleton()->edit_item(NULL);
  666. }
  667. void AnimationNodeBlendSpace2DEditor::_auto_triangles_toggled() {
  668. undo_redo->create_action(TTR("Toggle Auto Triangles"));
  669. undo_redo->add_do_method(blend_space.ptr(), "set_auto_triangles", auto_triangles->is_pressed());
  670. undo_redo->add_undo_method(blend_space.ptr(), "set_auto_triangles", blend_space->get_auto_triangles());
  671. undo_redo->add_do_method(this, "_update_space");
  672. undo_redo->add_undo_method(this, "_update_space");
  673. undo_redo->commit_action();
  674. }
  675. void AnimationNodeBlendSpace2DEditor::_bind_methods() {
  676. ClassDB::bind_method("_blend_space_gui_input", &AnimationNodeBlendSpace2DEditor::_blend_space_gui_input);
  677. ClassDB::bind_method("_blend_space_draw", &AnimationNodeBlendSpace2DEditor::_blend_space_draw);
  678. ClassDB::bind_method("_config_changed", &AnimationNodeBlendSpace2DEditor::_config_changed);
  679. ClassDB::bind_method("_labels_changed", &AnimationNodeBlendSpace2DEditor::_labels_changed);
  680. ClassDB::bind_method("_update_space", &AnimationNodeBlendSpace2DEditor::_update_space);
  681. ClassDB::bind_method("_snap_toggled", &AnimationNodeBlendSpace2DEditor::_snap_toggled);
  682. ClassDB::bind_method("_tool_switch", &AnimationNodeBlendSpace2DEditor::_tool_switch);
  683. ClassDB::bind_method("_erase_selected", &AnimationNodeBlendSpace2DEditor::_erase_selected);
  684. ClassDB::bind_method("_update_tool_erase", &AnimationNodeBlendSpace2DEditor::_update_tool_erase);
  685. ClassDB::bind_method("_edit_point_pos", &AnimationNodeBlendSpace2DEditor::_edit_point_pos);
  686. ClassDB::bind_method("_add_menu_type", &AnimationNodeBlendSpace2DEditor::_add_menu_type);
  687. ClassDB::bind_method("_add_animation_type", &AnimationNodeBlendSpace2DEditor::_add_animation_type);
  688. ClassDB::bind_method("_update_edited_point_pos", &AnimationNodeBlendSpace2DEditor::_update_edited_point_pos);
  689. ClassDB::bind_method("_open_editor", &AnimationNodeBlendSpace2DEditor::_open_editor);
  690. ClassDB::bind_method("_removed_from_graph", &AnimationNodeBlendSpace2DEditor::_removed_from_graph);
  691. ClassDB::bind_method("_auto_triangles_toggled", &AnimationNodeBlendSpace2DEditor::_auto_triangles_toggled);
  692. ClassDB::bind_method("_blend_space_changed", &AnimationNodeBlendSpace2DEditor::_blend_space_changed);
  693. ClassDB::bind_method("_file_opened", &AnimationNodeBlendSpace2DEditor::_file_opened);
  694. }
  695. AnimationNodeBlendSpace2DEditor *AnimationNodeBlendSpace2DEditor::singleton = NULL;
  696. AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() {
  697. singleton = this;
  698. updating = false;
  699. HBoxContainer *top_hb = memnew(HBoxContainer);
  700. add_child(top_hb);
  701. Ref<ButtonGroup> bg;
  702. bg.instance();
  703. tool_blend = memnew(ToolButton);
  704. tool_blend->set_toggle_mode(true);
  705. tool_blend->set_button_group(bg);
  706. top_hb->add_child(tool_blend);
  707. tool_blend->set_pressed(true);
  708. tool_blend->set_tooltip(TTR("Set the blending position within the space"));
  709. tool_blend->connect("pressed", this, "_tool_switch", varray(3));
  710. tool_select = memnew(ToolButton);
  711. tool_select->set_toggle_mode(true);
  712. tool_select->set_button_group(bg);
  713. top_hb->add_child(tool_select);
  714. tool_select->set_tooltip(TTR("Select and move points, create points with RMB."));
  715. tool_select->connect("pressed", this, "_tool_switch", varray(0));
  716. tool_create = memnew(ToolButton);
  717. tool_create->set_toggle_mode(true);
  718. tool_create->set_button_group(bg);
  719. top_hb->add_child(tool_create);
  720. tool_create->set_tooltip(TTR("Create points."));
  721. tool_create->connect("pressed", this, "_tool_switch", varray(1));
  722. tool_triangle = memnew(ToolButton);
  723. tool_triangle->set_toggle_mode(true);
  724. tool_triangle->set_button_group(bg);
  725. top_hb->add_child(tool_triangle);
  726. tool_triangle->set_tooltip(TTR("Create triangles by connecting points."));
  727. tool_triangle->connect("pressed", this, "_tool_switch", varray(2));
  728. tool_erase_sep = memnew(VSeparator);
  729. top_hb->add_child(tool_erase_sep);
  730. tool_erase = memnew(ToolButton);
  731. top_hb->add_child(tool_erase);
  732. tool_erase->set_tooltip(TTR("Erase points and triangles."));
  733. tool_erase->connect("pressed", this, "_erase_selected");
  734. tool_erase->set_disabled(true);
  735. top_hb->add_child(memnew(VSeparator));
  736. auto_triangles = memnew(ToolButton);
  737. top_hb->add_child(auto_triangles);
  738. auto_triangles->connect("pressed", this, "_auto_triangles_toggled");
  739. auto_triangles->set_toggle_mode(true);
  740. auto_triangles->set_tooltip(TTR("Generate blend triangles automatically (instead of manually)"));
  741. top_hb->add_child(memnew(VSeparator));
  742. snap = memnew(ToolButton);
  743. snap->set_toggle_mode(true);
  744. top_hb->add_child(snap);
  745. snap->set_pressed(true);
  746. snap->set_tooltip(TTR("Enable snap and show grid."));
  747. snap->connect("pressed", this, "_snap_toggled");
  748. snap_x = memnew(SpinBox);
  749. top_hb->add_child(snap_x);
  750. snap_x->set_prefix("x:");
  751. snap_x->set_min(0.01);
  752. snap_x->set_step(0.01);
  753. snap_x->set_max(1000);
  754. snap_y = memnew(SpinBox);
  755. top_hb->add_child(snap_y);
  756. snap_y->set_prefix("y:");
  757. snap_y->set_min(0.01);
  758. snap_y->set_step(0.01);
  759. snap_y->set_max(1000);
  760. top_hb->add_child(memnew(VSeparator));
  761. top_hb->add_child(memnew(Label(TTR("Blend:"))));
  762. interpolation = memnew(OptionButton);
  763. top_hb->add_child(interpolation);
  764. interpolation->connect("item_selected", this, "_config_changed");
  765. edit_hb = memnew(HBoxContainer);
  766. top_hb->add_child(edit_hb);
  767. edit_hb->add_child(memnew(VSeparator));
  768. edit_hb->add_child(memnew(Label(TTR("Point"))));
  769. edit_x = memnew(SpinBox);
  770. edit_hb->add_child(edit_x);
  771. edit_x->set_min(-1000);
  772. edit_x->set_step(0.01);
  773. edit_x->set_max(1000);
  774. edit_x->connect("value_changed", this, "_edit_point_pos");
  775. edit_y = memnew(SpinBox);
  776. edit_hb->add_child(edit_y);
  777. edit_y->set_min(-1000);
  778. edit_y->set_step(0.01);
  779. edit_y->set_max(1000);
  780. edit_y->connect("value_changed", this, "_edit_point_pos");
  781. open_editor = memnew(Button);
  782. edit_hb->add_child(open_editor);
  783. open_editor->set_text(TTR("Open Editor"));
  784. open_editor->connect("pressed", this, "_open_editor", varray(), CONNECT_DEFERRED);
  785. edit_hb->hide();
  786. open_editor->hide();
  787. HBoxContainer *main_hb = memnew(HBoxContainer);
  788. add_child(main_hb);
  789. main_hb->set_v_size_flags(SIZE_EXPAND_FILL);
  790. GridContainer *main_grid = memnew(GridContainer);
  791. main_grid->set_columns(2);
  792. main_hb->add_child(main_grid);
  793. main_grid->set_h_size_flags(SIZE_EXPAND_FILL);
  794. {
  795. VBoxContainer *left_vbox = memnew(VBoxContainer);
  796. main_grid->add_child(left_vbox);
  797. left_vbox->set_v_size_flags(SIZE_EXPAND_FILL);
  798. max_y_value = memnew(SpinBox);
  799. left_vbox->add_child(max_y_value);
  800. left_vbox->add_spacer();
  801. label_y = memnew(LineEdit);
  802. left_vbox->add_child(label_y);
  803. label_y->set_expand_to_text_length(true);
  804. left_vbox->add_spacer();
  805. min_y_value = memnew(SpinBox);
  806. left_vbox->add_child(min_y_value);
  807. max_y_value->set_max(10000);
  808. max_y_value->set_min(0.01);
  809. max_y_value->set_step(0.01);
  810. min_y_value->set_min(-10000);
  811. min_y_value->set_max(0);
  812. min_y_value->set_step(0.01);
  813. }
  814. panel = memnew(PanelContainer);
  815. panel->set_clip_contents(true);
  816. main_grid->add_child(panel);
  817. panel->set_h_size_flags(SIZE_EXPAND_FILL);
  818. blend_space_draw = memnew(Control);
  819. blend_space_draw->connect("gui_input", this, "_blend_space_gui_input");
  820. blend_space_draw->connect("draw", this, "_blend_space_draw");
  821. blend_space_draw->set_focus_mode(FOCUS_ALL);
  822. panel->add_child(blend_space_draw);
  823. main_grid->add_child(memnew(Control)); //empty bottom left
  824. {
  825. HBoxContainer *bottom_vbox = memnew(HBoxContainer);
  826. main_grid->add_child(bottom_vbox);
  827. bottom_vbox->set_h_size_flags(SIZE_EXPAND_FILL);
  828. min_x_value = memnew(SpinBox);
  829. bottom_vbox->add_child(min_x_value);
  830. bottom_vbox->add_spacer();
  831. label_x = memnew(LineEdit);
  832. bottom_vbox->add_child(label_x);
  833. label_x->set_expand_to_text_length(true);
  834. bottom_vbox->add_spacer();
  835. max_x_value = memnew(SpinBox);
  836. bottom_vbox->add_child(max_x_value);
  837. max_x_value->set_max(10000);
  838. max_x_value->set_min(0.01);
  839. max_x_value->set_step(0.01);
  840. min_x_value->set_min(-10000);
  841. min_x_value->set_max(0);
  842. min_x_value->set_step(0.01);
  843. }
  844. snap_x->connect("value_changed", this, "_config_changed");
  845. snap_y->connect("value_changed", this, "_config_changed");
  846. max_x_value->connect("value_changed", this, "_config_changed");
  847. min_x_value->connect("value_changed", this, "_config_changed");
  848. max_y_value->connect("value_changed", this, "_config_changed");
  849. min_y_value->connect("value_changed", this, "_config_changed");
  850. label_x->connect("text_changed", this, "_labels_changed");
  851. label_y->connect("text_changed", this, "_labels_changed");
  852. error_panel = memnew(PanelContainer);
  853. add_child(error_panel);
  854. error_label = memnew(Label);
  855. error_panel->add_child(error_label);
  856. error_label->set_text("eh");
  857. undo_redo = EditorNode::get_singleton()->get_undo_redo();
  858. set_custom_minimum_size(Size2(0, 300 * EDSCALE));
  859. menu = memnew(PopupMenu);
  860. add_child(menu);
  861. menu->connect("id_pressed", this, "_add_menu_type");
  862. animations_menu = memnew(PopupMenu);
  863. menu->add_child(animations_menu);
  864. animations_menu->set_name("animations");
  865. animations_menu->connect("index_pressed", this, "_add_animation_type");
  866. open_file = memnew(EditorFileDialog);
  867. add_child(open_file);
  868. open_file->set_title(TTR("Open Animation Node"));
  869. open_file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
  870. open_file->connect("file_selected", this, "_file_opened");
  871. undo_redo = EditorNode::get_singleton()->get_undo_redo();
  872. selected_point = -1;
  873. selected_triangle = -1;
  874. dragging_selected = false;
  875. dragging_selected_attempt = false;
  876. }