animation_track_editor_plugins.cpp 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351
  1. /*************************************************************************/
  2. /* animation_track_editor_plugins.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2020 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_track_editor_plugins.h"
  31. #include "editor/audio_stream_preview.h"
  32. #include "editor_resource_preview.h"
  33. #include "editor_scale.h"
  34. #include "scene/2d/animated_sprite_2d.h"
  35. #include "scene/2d/sprite_2d.h"
  36. #include "scene/3d/sprite_3d.h"
  37. #include "scene/animation/animation_player.h"
  38. #include "servers/audio/audio_stream.h"
  39. /// BOOL ///
  40. int AnimationTrackEditBool::get_key_height() const {
  41. Ref<Texture2D> checked = get_theme_icon("checked", "CheckBox");
  42. return checked->get_height();
  43. }
  44. Rect2 AnimationTrackEditBool::get_key_rect(int p_index, float p_pixels_sec) {
  45. Ref<Texture2D> checked = get_theme_icon("checked", "CheckBox");
  46. return Rect2(-checked->get_width() / 2, 0, checked->get_width(), get_size().height);
  47. }
  48. bool AnimationTrackEditBool::is_key_selectable_by_distance() const {
  49. return false;
  50. }
  51. void AnimationTrackEditBool::draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right) {
  52. bool checked = get_animation()->track_get_key_value(get_track(), p_index);
  53. Ref<Texture2D> icon = get_theme_icon(checked ? "checked" : "unchecked", "CheckBox");
  54. Vector2 ofs(p_x - icon->get_width() / 2, int(get_size().height - icon->get_height()) / 2);
  55. if (ofs.x + icon->get_width() / 2 < p_clip_left)
  56. return;
  57. if (ofs.x + icon->get_width() / 2 > p_clip_right)
  58. return;
  59. draw_texture(icon, ofs);
  60. if (p_selected) {
  61. Color color = get_theme_color("accent_color", "Editor");
  62. draw_rect_clipped(Rect2(ofs, icon->get_size()), color, false);
  63. }
  64. }
  65. /// COLOR ///
  66. int AnimationTrackEditColor::get_key_height() const {
  67. Ref<Font> font = get_theme_font("font", "Label");
  68. return font->get_height() * 0.8;
  69. }
  70. Rect2 AnimationTrackEditColor::get_key_rect(int p_index, float p_pixels_sec) {
  71. Ref<Font> font = get_theme_font("font", "Label");
  72. int fh = font->get_height() * 0.8;
  73. return Rect2(-fh / 2, 0, fh, get_size().height);
  74. }
  75. bool AnimationTrackEditColor::is_key_selectable_by_distance() const {
  76. return false;
  77. }
  78. void AnimationTrackEditColor::draw_key_link(int p_index, float p_pixels_sec, int p_x, int p_next_x, int p_clip_left, int p_clip_right) {
  79. Ref<Font> font = get_theme_font("font", "Label");
  80. int fh = (font->get_height() * 0.8);
  81. int x_from = p_x + fh / 2 - 1;
  82. int x_to = p_next_x - fh / 2 + 1;
  83. fh /= 3;
  84. if (x_from > p_clip_right || x_to < p_clip_left)
  85. return;
  86. Color color = get_animation()->track_get_key_value(get_track(), p_index);
  87. Color color_next = get_animation()->track_get_key_value(get_track(), p_index + 1);
  88. if (x_from < p_clip_left) {
  89. float c = float(p_clip_left - x_from) / (x_to - x_from);
  90. color = color.lerp(color_next, c);
  91. x_from = p_clip_left;
  92. }
  93. if (x_to > p_clip_right) {
  94. float c = float(p_clip_right - x_from) / (x_to - x_from);
  95. color_next = color.lerp(color_next, c);
  96. x_to = p_clip_right;
  97. }
  98. int y_from = (get_size().height - fh) / 2;
  99. Vector<Vector2> points;
  100. Vector<Color> colors;
  101. points.push_back(Vector2(x_from, y_from));
  102. colors.push_back(color);
  103. points.push_back(Vector2(x_to, y_from));
  104. colors.push_back(color_next);
  105. points.push_back(Vector2(x_to, y_from + fh));
  106. colors.push_back(color_next);
  107. points.push_back(Vector2(x_from, y_from + fh));
  108. colors.push_back(color);
  109. draw_primitive(points, colors, Vector<Vector2>());
  110. }
  111. void AnimationTrackEditColor::draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right) {
  112. Color color = get_animation()->track_get_key_value(get_track(), p_index);
  113. Ref<Font> font = get_theme_font("font", "Label");
  114. int fh = font->get_height() * 0.8;
  115. Rect2 rect(Vector2(p_x - fh / 2, int(get_size().height - fh) / 2), Size2(fh, fh));
  116. draw_rect_clipped(Rect2(rect.position, rect.size / 2), Color(0.4, 0.4, 0.4));
  117. draw_rect_clipped(Rect2(rect.position + rect.size / 2, rect.size / 2), Color(0.4, 0.4, 0.4));
  118. draw_rect_clipped(Rect2(rect.position + Vector2(rect.size.x / 2, 0), rect.size / 2), Color(0.6, 0.6, 0.6));
  119. draw_rect_clipped(Rect2(rect.position + Vector2(0, rect.size.y / 2), rect.size / 2), Color(0.6, 0.6, 0.6));
  120. draw_rect_clipped(rect, color);
  121. if (p_selected) {
  122. Color accent = get_theme_color("accent_color", "Editor");
  123. draw_rect_clipped(rect, accent, false);
  124. }
  125. }
  126. /// AUDIO ///
  127. void AnimationTrackEditAudio::_preview_changed(ObjectID p_which) {
  128. Object *object = ObjectDB::get_instance(id);
  129. if (!object)
  130. return;
  131. Ref<AudioStream> stream = object->call("get_stream");
  132. if (stream.is_valid() && stream->get_instance_id() == p_which) {
  133. update();
  134. }
  135. }
  136. int AnimationTrackEditAudio::get_key_height() const {
  137. if (!ObjectDB::get_instance(id)) {
  138. return AnimationTrackEdit::get_key_height();
  139. }
  140. Ref<Font> font = get_theme_font("font", "Label");
  141. return int(font->get_height() * 1.5);
  142. }
  143. Rect2 AnimationTrackEditAudio::get_key_rect(int p_index, float p_pixels_sec) {
  144. Object *object = ObjectDB::get_instance(id);
  145. if (!object) {
  146. return AnimationTrackEdit::get_key_rect(p_index, p_pixels_sec);
  147. }
  148. Ref<AudioStream> stream = object->call("get_stream");
  149. if (!stream.is_valid()) {
  150. return AnimationTrackEdit::get_key_rect(p_index, p_pixels_sec);
  151. }
  152. bool play = get_animation()->track_get_key_value(get_track(), p_index);
  153. if (play) {
  154. float len = stream->get_length();
  155. if (len == 0) {
  156. Ref<AudioStreamPreview> preview = AudioStreamPreviewGenerator::get_singleton()->generate_preview(stream);
  157. len = preview->get_length();
  158. }
  159. if (get_animation()->track_get_key_count(get_track()) > p_index + 1) {
  160. len = MIN(len, get_animation()->track_get_key_time(get_track(), p_index + 1) - get_animation()->track_get_key_time(get_track(), p_index));
  161. }
  162. return Rect2(0, 0, len * p_pixels_sec, get_size().height);
  163. } else {
  164. Ref<Font> font = get_theme_font("font", "Label");
  165. int fh = font->get_height() * 0.8;
  166. return Rect2(0, 0, fh, get_size().height);
  167. }
  168. }
  169. bool AnimationTrackEditAudio::is_key_selectable_by_distance() const {
  170. return false;
  171. }
  172. void AnimationTrackEditAudio::draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right) {
  173. Object *object = ObjectDB::get_instance(id);
  174. if (!object) {
  175. AnimationTrackEdit::draw_key(p_index, p_pixels_sec, p_x, p_selected, p_clip_left, p_clip_right);
  176. return;
  177. }
  178. Ref<AudioStream> stream = object->call("get_stream");
  179. if (!stream.is_valid()) {
  180. AnimationTrackEdit::draw_key(p_index, p_pixels_sec, p_x, p_selected, p_clip_left, p_clip_right);
  181. return;
  182. }
  183. bool play = get_animation()->track_get_key_value(get_track(), p_index);
  184. if (play) {
  185. float len = stream->get_length();
  186. Ref<AudioStreamPreview> preview = AudioStreamPreviewGenerator::get_singleton()->generate_preview(stream);
  187. float preview_len = preview->get_length();
  188. if (len == 0) {
  189. len = preview_len;
  190. }
  191. int pixel_len = len * p_pixels_sec;
  192. int pixel_begin = p_x;
  193. int pixel_end = p_x + pixel_len;
  194. if (pixel_end < p_clip_left)
  195. return;
  196. if (pixel_begin > p_clip_right)
  197. return;
  198. int from_x = MAX(pixel_begin, p_clip_left);
  199. int to_x = MIN(pixel_end, p_clip_right);
  200. if (get_animation()->track_get_key_count(get_track()) > p_index + 1) {
  201. float limit = MIN(len, get_animation()->track_get_key_time(get_track(), p_index + 1) - get_animation()->track_get_key_time(get_track(), p_index));
  202. int limit_x = pixel_begin + limit * p_pixels_sec;
  203. to_x = MIN(limit_x, to_x);
  204. }
  205. if (to_x <= from_x)
  206. return;
  207. Ref<Font> font = get_theme_font("font", "Label");
  208. float fh = int(font->get_height() * 1.5);
  209. Rect2 rect = Rect2(from_x, (get_size().height - fh) / 2, to_x - from_x, fh);
  210. draw_rect(rect, Color(0.25, 0.25, 0.25));
  211. Vector<Vector2> lines;
  212. lines.resize((to_x - from_x + 1) * 2);
  213. preview_len = preview->get_length();
  214. for (int i = from_x; i < to_x; i++) {
  215. float ofs = (i - pixel_begin) * preview_len / pixel_len;
  216. float ofs_n = ((i + 1) - pixel_begin) * preview_len / pixel_len;
  217. float max = preview->get_max(ofs, ofs_n) * 0.5 + 0.5;
  218. float min = preview->get_min(ofs, ofs_n) * 0.5 + 0.5;
  219. int idx = i - from_x;
  220. lines.write[idx * 2 + 0] = Vector2(i, rect.position.y + min * rect.size.y);
  221. lines.write[idx * 2 + 1] = Vector2(i, rect.position.y + max * rect.size.y);
  222. }
  223. Vector<Color> color;
  224. color.push_back(Color(0.75, 0.75, 0.75));
  225. RS::get_singleton()->canvas_item_add_multiline(get_canvas_item(), lines, color);
  226. if (p_selected) {
  227. Color accent = get_theme_color("accent_color", "Editor");
  228. draw_rect(rect, accent, false);
  229. }
  230. } else {
  231. Ref<Font> font = get_theme_font("font", "Label");
  232. int fh = font->get_height() * 0.8;
  233. Rect2 rect(Vector2(p_x, int(get_size().height - fh) / 2), Size2(fh, fh));
  234. Color color = get_theme_color("font_color", "Label");
  235. draw_rect(rect, color);
  236. if (p_selected) {
  237. Color accent = get_theme_color("accent_color", "Editor");
  238. draw_rect(rect, accent, false);
  239. }
  240. }
  241. }
  242. void AnimationTrackEditAudio::set_node(Object *p_object) {
  243. id = p_object->get_instance_id();
  244. }
  245. void AnimationTrackEditAudio::_bind_methods() {
  246. }
  247. AnimationTrackEditAudio::AnimationTrackEditAudio() {
  248. AudioStreamPreviewGenerator::get_singleton()->connect("preview_updated", callable_mp(this, &AnimationTrackEditAudio::_preview_changed));
  249. }
  250. /// SPRITE FRAME / FRAME_COORDS ///
  251. int AnimationTrackEditSpriteFrame::get_key_height() const {
  252. if (!ObjectDB::get_instance(id)) {
  253. return AnimationTrackEdit::get_key_height();
  254. }
  255. Ref<Font> font = get_theme_font("font", "Label");
  256. return int(font->get_height() * 2);
  257. }
  258. Rect2 AnimationTrackEditSpriteFrame::get_key_rect(int p_index, float p_pixels_sec) {
  259. Object *object = ObjectDB::get_instance(id);
  260. if (!object) {
  261. return AnimationTrackEdit::get_key_rect(p_index, p_pixels_sec);
  262. }
  263. Size2 size;
  264. if (Object::cast_to<Sprite2D>(object) || Object::cast_to<Sprite3D>(object)) {
  265. Ref<Texture2D> texture = object->call("get_texture");
  266. if (!texture.is_valid()) {
  267. return AnimationTrackEdit::get_key_rect(p_index, p_pixels_sec);
  268. }
  269. size = texture->get_size();
  270. if (bool(object->call("is_region"))) {
  271. size = Rect2(object->call("get_region_rect")).size;
  272. }
  273. int hframes = object->call("get_hframes");
  274. int vframes = object->call("get_vframes");
  275. if (hframes > 1) {
  276. size.x /= hframes;
  277. }
  278. if (vframes > 1) {
  279. size.y /= vframes;
  280. }
  281. } else if (Object::cast_to<AnimatedSprite2D>(object) || Object::cast_to<AnimatedSprite3D>(object)) {
  282. Ref<SpriteFrames> sf = object->call("get_sprite_frames");
  283. if (sf.is_null()) {
  284. return AnimationTrackEdit::get_key_rect(p_index, p_pixels_sec);
  285. }
  286. List<StringName> animations;
  287. sf->get_animation_list(&animations);
  288. int frame = get_animation()->track_get_key_value(get_track(), p_index);
  289. String animation;
  290. if (animations.size() == 1) {
  291. animation = animations.front()->get();
  292. } else {
  293. // Go through other track to find if animation is set
  294. String animation_path = get_animation()->track_get_path(get_track());
  295. animation_path = animation_path.replace(":frame", ":animation");
  296. int animation_track = get_animation()->find_track(animation_path);
  297. float track_time = get_animation()->track_get_key_time(get_track(), p_index);
  298. int animaiton_index = get_animation()->track_find_key(animation_track, track_time);
  299. animation = get_animation()->track_get_key_value(animation_track, animaiton_index);
  300. }
  301. Ref<Texture2D> texture = sf->get_frame(animation, frame);
  302. if (!texture.is_valid()) {
  303. return AnimationTrackEdit::get_key_rect(p_index, p_pixels_sec);
  304. }
  305. size = texture->get_size();
  306. }
  307. size = size.floor();
  308. Ref<Font> font = get_theme_font("font", "Label");
  309. int height = int(font->get_height() * 2);
  310. int width = height * size.width / size.height;
  311. return Rect2(0, 0, width, get_size().height);
  312. }
  313. bool AnimationTrackEditSpriteFrame::is_key_selectable_by_distance() const {
  314. return false;
  315. }
  316. void AnimationTrackEditSpriteFrame::draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right) {
  317. Object *object = ObjectDB::get_instance(id);
  318. if (!object) {
  319. AnimationTrackEdit::draw_key(p_index, p_pixels_sec, p_x, p_selected, p_clip_left, p_clip_right);
  320. return;
  321. }
  322. Ref<Texture2D> texture;
  323. Rect2 region;
  324. if (Object::cast_to<Sprite2D>(object) || Object::cast_to<Sprite3D>(object)) {
  325. texture = object->call("get_texture");
  326. if (!texture.is_valid()) {
  327. AnimationTrackEdit::draw_key(p_index, p_pixels_sec, p_x, p_selected, p_clip_left, p_clip_right);
  328. return;
  329. }
  330. int hframes = object->call("get_hframes");
  331. int vframes = object->call("get_vframes");
  332. Vector2 coords;
  333. if (is_coords) {
  334. coords = get_animation()->track_get_key_value(get_track(), p_index);
  335. } else {
  336. int frame = get_animation()->track_get_key_value(get_track(), p_index);
  337. coords.x = frame % hframes;
  338. coords.y = frame / hframes;
  339. }
  340. region.size = texture->get_size();
  341. if (bool(object->call("is_region"))) {
  342. region = Rect2(object->call("get_region_rect"));
  343. }
  344. if (hframes > 1) {
  345. region.size.x /= hframes;
  346. }
  347. if (vframes > 1) {
  348. region.size.y /= vframes;
  349. }
  350. region.position.x += region.size.x * coords.x;
  351. region.position.y += region.size.y * coords.y;
  352. } else if (Object::cast_to<AnimatedSprite2D>(object) || Object::cast_to<AnimatedSprite3D>(object)) {
  353. Ref<SpriteFrames> sf = object->call("get_sprite_frames");
  354. if (sf.is_null()) {
  355. AnimationTrackEdit::draw_key(p_index, p_pixels_sec, p_x, p_selected, p_clip_left, p_clip_right);
  356. return;
  357. }
  358. List<StringName> animations;
  359. sf->get_animation_list(&animations);
  360. int frame = get_animation()->track_get_key_value(get_track(), p_index);
  361. String animation;
  362. if (animations.size() == 1) {
  363. animation = animations.front()->get();
  364. } else {
  365. // Go through other track to find if animation is set
  366. String animation_path = get_animation()->track_get_path(get_track());
  367. animation_path = animation_path.replace(":frame", ":animation");
  368. int animation_track = get_animation()->find_track(animation_path);
  369. float track_time = get_animation()->track_get_key_time(get_track(), p_index);
  370. int animaiton_index = get_animation()->track_find_key(animation_track, track_time);
  371. animation = get_animation()->track_get_key_value(animation_track, animaiton_index);
  372. }
  373. texture = sf->get_frame(animation, frame);
  374. if (!texture.is_valid()) {
  375. AnimationTrackEdit::draw_key(p_index, p_pixels_sec, p_x, p_selected, p_clip_left, p_clip_right);
  376. return;
  377. }
  378. region.size = texture->get_size();
  379. }
  380. Ref<Font> font = get_theme_font("font", "Label");
  381. int height = int(font->get_height() * 2);
  382. int width = height * region.size.width / region.size.height;
  383. Rect2 rect(p_x, int(get_size().height - height) / 2, width, height);
  384. if (rect.position.x + rect.size.x < p_clip_left)
  385. return;
  386. if (rect.position.x > p_clip_right)
  387. return;
  388. Color accent = get_theme_color("accent_color", "Editor");
  389. Color bg = accent;
  390. bg.a = 0.15;
  391. draw_rect_clipped(rect, bg);
  392. draw_texture_region_clipped(texture, rect, region);
  393. if (p_selected) {
  394. draw_rect_clipped(rect, accent, false);
  395. }
  396. }
  397. void AnimationTrackEditSpriteFrame::set_node(Object *p_object) {
  398. id = p_object->get_instance_id();
  399. }
  400. void AnimationTrackEditSpriteFrame::set_as_coords() {
  401. is_coords = true;
  402. }
  403. /// SUB ANIMATION ///
  404. int AnimationTrackEditSubAnim::get_key_height() const {
  405. if (!ObjectDB::get_instance(id)) {
  406. return AnimationTrackEdit::get_key_height();
  407. }
  408. Ref<Font> font = get_theme_font("font", "Label");
  409. return int(font->get_height() * 1.5);
  410. }
  411. Rect2 AnimationTrackEditSubAnim::get_key_rect(int p_index, float p_pixels_sec) {
  412. Object *object = ObjectDB::get_instance(id);
  413. if (!object) {
  414. return AnimationTrackEdit::get_key_rect(p_index, p_pixels_sec);
  415. }
  416. AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(object);
  417. if (!ap) {
  418. return AnimationTrackEdit::get_key_rect(p_index, p_pixels_sec);
  419. }
  420. String anim = get_animation()->track_get_key_value(get_track(), p_index);
  421. if (anim != "[stop]" && ap->has_animation(anim)) {
  422. float len = ap->get_animation(anim)->get_length();
  423. if (get_animation()->track_get_key_count(get_track()) > p_index + 1) {
  424. len = MIN(len, get_animation()->track_get_key_time(get_track(), p_index + 1) - get_animation()->track_get_key_time(get_track(), p_index));
  425. }
  426. return Rect2(0, 0, len * p_pixels_sec, get_size().height);
  427. } else {
  428. Ref<Font> font = get_theme_font("font", "Label");
  429. int fh = font->get_height() * 0.8;
  430. return Rect2(0, 0, fh, get_size().height);
  431. }
  432. }
  433. bool AnimationTrackEditSubAnim::is_key_selectable_by_distance() const {
  434. return false;
  435. }
  436. void AnimationTrackEditSubAnim::draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right) {
  437. Object *object = ObjectDB::get_instance(id);
  438. if (!object) {
  439. AnimationTrackEdit::draw_key(p_index, p_pixels_sec, p_x, p_selected, p_clip_left, p_clip_right);
  440. return;
  441. }
  442. AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(object);
  443. if (!ap) {
  444. AnimationTrackEdit::draw_key(p_index, p_pixels_sec, p_x, p_selected, p_clip_left, p_clip_right);
  445. return;
  446. }
  447. String anim = get_animation()->track_get_key_value(get_track(), p_index);
  448. if (anim != "[stop]" && ap->has_animation(anim)) {
  449. float len = ap->get_animation(anim)->get_length();
  450. if (get_animation()->track_get_key_count(get_track()) > p_index + 1) {
  451. len = MIN(len, get_animation()->track_get_key_time(get_track(), p_index + 1) - get_animation()->track_get_key_time(get_track(), p_index));
  452. }
  453. int pixel_len = len * p_pixels_sec;
  454. int pixel_begin = p_x;
  455. int pixel_end = p_x + pixel_len;
  456. if (pixel_end < p_clip_left)
  457. return;
  458. if (pixel_begin > p_clip_right)
  459. return;
  460. int from_x = MAX(pixel_begin, p_clip_left);
  461. int to_x = MIN(pixel_end, p_clip_right);
  462. if (to_x <= from_x)
  463. return;
  464. Ref<Font> font = get_theme_font("font", "Label");
  465. int fh = font->get_height() * 1.5;
  466. Rect2 rect(from_x, int(get_size().height - fh) / 2, to_x - from_x, fh);
  467. Color color = get_theme_color("font_color", "Label");
  468. Color bg = color;
  469. bg.r = 1 - color.r;
  470. bg.g = 1 - color.g;
  471. bg.b = 1 - color.b;
  472. draw_rect(rect, bg);
  473. Vector<Vector2> lines;
  474. Vector<Color> colorv;
  475. {
  476. Ref<Animation> animation = ap->get_animation(anim);
  477. for (int i = 0; i < animation->get_track_count(); i++) {
  478. float h = (rect.size.height - 2) / animation->get_track_count();
  479. int y = 2 + h * i + h / 2;
  480. for (int j = 0; j < animation->track_get_key_count(i); j++) {
  481. float ofs = animation->track_get_key_time(i, j);
  482. int x = p_x + ofs * p_pixels_sec + 2;
  483. if (x < from_x || x >= (to_x - 4))
  484. continue;
  485. lines.push_back(Point2(x, y));
  486. lines.push_back(Point2(x + 1, y));
  487. }
  488. }
  489. colorv.push_back(color);
  490. }
  491. if (lines.size() > 2) {
  492. RS::get_singleton()->canvas_item_add_multiline(get_canvas_item(), lines, colorv);
  493. }
  494. int limit = to_x - from_x - 4;
  495. if (limit > 0) {
  496. draw_string(font, Point2(from_x + 2, int(get_size().height - font->get_height()) / 2 + font->get_ascent()), anim, color);
  497. }
  498. if (p_selected) {
  499. Color accent = get_theme_color("accent_color", "Editor");
  500. draw_rect(rect, accent, false);
  501. }
  502. } else {
  503. Ref<Font> font = get_theme_font("font", "Label");
  504. int fh = font->get_height() * 0.8;
  505. Rect2 rect(Vector2(p_x, int(get_size().height - fh) / 2), Size2(fh, fh));
  506. Color color = get_theme_color("font_color", "Label");
  507. draw_rect(rect, color);
  508. if (p_selected) {
  509. Color accent = get_theme_color("accent_color", "Editor");
  510. draw_rect(rect, accent, false);
  511. }
  512. }
  513. }
  514. void AnimationTrackEditSubAnim::set_node(Object *p_object) {
  515. id = p_object->get_instance_id();
  516. }
  517. //// VOLUME DB ////
  518. int AnimationTrackEditVolumeDB::get_key_height() const {
  519. Ref<Texture2D> volume_texture = get_theme_icon("ColorTrackVu", "EditorIcons");
  520. return volume_texture->get_height() * 1.2;
  521. }
  522. void AnimationTrackEditVolumeDB::draw_bg(int p_clip_left, int p_clip_right) {
  523. Ref<Texture2D> volume_texture = get_theme_icon("ColorTrackVu", "EditorIcons");
  524. int tex_h = volume_texture->get_height();
  525. int y_from = (get_size().height - tex_h) / 2;
  526. int y_size = tex_h;
  527. Color color(1, 1, 1, 0.3);
  528. draw_texture_rect(volume_texture, Rect2(p_clip_left, y_from, p_clip_right - p_clip_left, y_from + y_size), false, color);
  529. }
  530. void AnimationTrackEditVolumeDB::draw_fg(int p_clip_left, int p_clip_right) {
  531. Ref<Texture2D> volume_texture = get_theme_icon("ColorTrackVu", "EditorIcons");
  532. int tex_h = volume_texture->get_height();
  533. int y_from = (get_size().height - tex_h) / 2;
  534. int db0 = y_from + (24 / 80.0) * tex_h;
  535. draw_line(Vector2(p_clip_left, db0), Vector2(p_clip_right, db0), Color(1, 1, 1, 0.3));
  536. }
  537. void AnimationTrackEditVolumeDB::draw_key_link(int p_index, float p_pixels_sec, int p_x, int p_next_x, int p_clip_left, int p_clip_right) {
  538. if (p_x > p_clip_right || p_next_x < p_clip_left)
  539. return;
  540. float db = get_animation()->track_get_key_value(get_track(), p_index);
  541. float db_n = get_animation()->track_get_key_value(get_track(), p_index + 1);
  542. db = CLAMP(db, -60, 24);
  543. db_n = CLAMP(db_n, -60, 24);
  544. float h = 1.0 - ((db + 60) / 84.0);
  545. float h_n = 1.0 - ((db_n + 60) / 84.0);
  546. int from_x = p_x;
  547. int to_x = p_next_x;
  548. if (from_x < p_clip_left) {
  549. h = Math::lerp(h, h_n, float(p_clip_left - from_x) / float(to_x - from_x));
  550. from_x = p_clip_left;
  551. }
  552. if (to_x > p_clip_right) {
  553. h_n = Math::lerp(h, h_n, float(p_clip_right - from_x) / float(to_x - from_x));
  554. to_x = p_clip_right;
  555. }
  556. Ref<Texture2D> volume_texture = get_theme_icon("ColorTrackVu", "EditorIcons");
  557. int tex_h = volume_texture->get_height();
  558. int y_from = (get_size().height - tex_h) / 2;
  559. Color color = get_theme_color("font_color", "Label");
  560. color.a *= 0.7;
  561. draw_line(Point2(from_x, y_from + h * tex_h), Point2(to_x, y_from + h_n * tex_h), color, 2);
  562. }
  563. ////////////////////////
  564. /// AUDIO ///
  565. void AnimationTrackEditTypeAudio::_preview_changed(ObjectID p_which) {
  566. for (int i = 0; i < get_animation()->track_get_key_count(get_track()); i++) {
  567. Ref<AudioStream> stream = get_animation()->audio_track_get_key_stream(get_track(), i);
  568. if (stream.is_valid() && stream->get_instance_id() == p_which) {
  569. update();
  570. return;
  571. }
  572. }
  573. }
  574. int AnimationTrackEditTypeAudio::get_key_height() const {
  575. Ref<Font> font = get_theme_font("font", "Label");
  576. return int(font->get_height() * 1.5);
  577. }
  578. Rect2 AnimationTrackEditTypeAudio::get_key_rect(int p_index, float p_pixels_sec) {
  579. Ref<AudioStream> stream = get_animation()->audio_track_get_key_stream(get_track(), p_index);
  580. if (!stream.is_valid()) {
  581. return AnimationTrackEdit::get_key_rect(p_index, p_pixels_sec);
  582. }
  583. float start_ofs = get_animation()->audio_track_get_key_start_offset(get_track(), p_index);
  584. float end_ofs = get_animation()->audio_track_get_key_end_offset(get_track(), p_index);
  585. float len = stream->get_length();
  586. if (len == 0) {
  587. Ref<AudioStreamPreview> preview = AudioStreamPreviewGenerator::get_singleton()->generate_preview(stream);
  588. len = preview->get_length();
  589. }
  590. len -= end_ofs;
  591. len -= start_ofs;
  592. if (len <= 0.001) {
  593. len = 0.001;
  594. }
  595. if (get_animation()->track_get_key_count(get_track()) > p_index + 1) {
  596. len = MIN(len, get_animation()->track_get_key_time(get_track(), p_index + 1) - get_animation()->track_get_key_time(get_track(), p_index));
  597. }
  598. return Rect2(0, 0, len * p_pixels_sec, get_size().height);
  599. }
  600. bool AnimationTrackEditTypeAudio::is_key_selectable_by_distance() const {
  601. return false;
  602. }
  603. void AnimationTrackEditTypeAudio::draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right) {
  604. Ref<AudioStream> stream = get_animation()->audio_track_get_key_stream(get_track(), p_index);
  605. if (!stream.is_valid()) {
  606. AnimationTrackEdit::draw_key(p_index, p_pixels_sec, p_x, p_selected, p_clip_left, p_clip_right);
  607. return;
  608. }
  609. float start_ofs = get_animation()->audio_track_get_key_start_offset(get_track(), p_index);
  610. float end_ofs = get_animation()->audio_track_get_key_end_offset(get_track(), p_index);
  611. if (len_resizing && p_index == len_resizing_index) {
  612. float ofs_local = -len_resizing_rel / get_timeline()->get_zoom_scale();
  613. if (len_resizing_start) {
  614. start_ofs += ofs_local;
  615. if (start_ofs < 0)
  616. start_ofs = 0;
  617. } else {
  618. end_ofs += ofs_local;
  619. if (end_ofs < 0)
  620. end_ofs = 0;
  621. }
  622. }
  623. Ref<Font> font = get_theme_font("font", "Label");
  624. float fh = int(font->get_height() * 1.5);
  625. float len = stream->get_length();
  626. Ref<AudioStreamPreview> preview = AudioStreamPreviewGenerator::get_singleton()->generate_preview(stream);
  627. float preview_len = preview->get_length();
  628. if (len == 0) {
  629. len = preview_len;
  630. }
  631. int pixel_total_len = len * p_pixels_sec;
  632. len -= end_ofs;
  633. len -= start_ofs;
  634. if (len <= 0.001) {
  635. len = 0.001;
  636. }
  637. int pixel_len = len * p_pixels_sec;
  638. int pixel_begin = p_x;
  639. int pixel_end = p_x + pixel_len;
  640. if (pixel_end < p_clip_left)
  641. return;
  642. if (pixel_begin > p_clip_right)
  643. return;
  644. int from_x = MAX(pixel_begin, p_clip_left);
  645. int to_x = MIN(pixel_end, p_clip_right);
  646. if (get_animation()->track_get_key_count(get_track()) > p_index + 1) {
  647. float limit = MIN(len, get_animation()->track_get_key_time(get_track(), p_index + 1) - get_animation()->track_get_key_time(get_track(), p_index));
  648. int limit_x = pixel_begin + limit * p_pixels_sec;
  649. to_x = MIN(limit_x, to_x);
  650. }
  651. if (to_x <= from_x) {
  652. to_x = from_x + 1;
  653. }
  654. int h = get_size().height;
  655. Rect2 rect = Rect2(from_x, (h - fh) / 2, to_x - from_x, fh);
  656. draw_rect(rect, Color(0.25, 0.25, 0.25));
  657. Vector<Vector2> lines;
  658. lines.resize((to_x - from_x + 1) * 2);
  659. preview_len = preview->get_length();
  660. for (int i = from_x; i < to_x; i++) {
  661. float ofs = (i - pixel_begin) * preview_len / pixel_total_len;
  662. float ofs_n = ((i + 1) - pixel_begin) * preview_len / pixel_total_len;
  663. ofs += start_ofs;
  664. ofs_n += start_ofs;
  665. float max = preview->get_max(ofs, ofs_n) * 0.5 + 0.5;
  666. float min = preview->get_min(ofs, ofs_n) * 0.5 + 0.5;
  667. int idx = i - from_x;
  668. lines.write[idx * 2 + 0] = Vector2(i, rect.position.y + min * rect.size.y);
  669. lines.write[idx * 2 + 1] = Vector2(i, rect.position.y + max * rect.size.y);
  670. }
  671. Vector<Color> color;
  672. color.push_back(Color(0.75, 0.75, 0.75));
  673. RS::get_singleton()->canvas_item_add_multiline(get_canvas_item(), lines, color);
  674. Color cut_color = get_theme_color("accent_color", "Editor");
  675. cut_color.a = 0.7;
  676. if (start_ofs > 0 && pixel_begin > p_clip_left) {
  677. draw_rect(Rect2(pixel_begin, rect.position.y, 1, rect.size.y), cut_color);
  678. }
  679. if (end_ofs > 0 && pixel_end < p_clip_right) {
  680. draw_rect(Rect2(pixel_end, rect.position.y, 1, rect.size.y), cut_color);
  681. }
  682. if (p_selected) {
  683. Color accent = get_theme_color("accent_color", "Editor");
  684. draw_rect(rect, accent, false);
  685. }
  686. }
  687. void AnimationTrackEditTypeAudio::_bind_methods() {
  688. }
  689. AnimationTrackEditTypeAudio::AnimationTrackEditTypeAudio() {
  690. AudioStreamPreviewGenerator::get_singleton()->connect("preview_updated", callable_mp(this, &AnimationTrackEditTypeAudio::_preview_changed));
  691. len_resizing = false;
  692. }
  693. bool AnimationTrackEditTypeAudio::can_drop_data(const Point2 &p_point, const Variant &p_data) const {
  694. if (p_point.x > get_timeline()->get_name_limit() && p_point.x < get_size().width - get_timeline()->get_buttons_width()) {
  695. Dictionary drag_data = p_data;
  696. if (drag_data.has("type") && String(drag_data["type"]) == "resource") {
  697. Ref<AudioStream> res = drag_data["resource"];
  698. if (res.is_valid()) {
  699. return true;
  700. }
  701. }
  702. if (drag_data.has("type") && String(drag_data["type"]) == "files") {
  703. Vector<String> files = drag_data["files"];
  704. if (files.size() == 1) {
  705. String file = files[0];
  706. Ref<AudioStream> res = ResourceLoader::load(file);
  707. if (res.is_valid()) {
  708. return true;
  709. }
  710. }
  711. }
  712. }
  713. return AnimationTrackEdit::can_drop_data(p_point, p_data);
  714. }
  715. void AnimationTrackEditTypeAudio::drop_data(const Point2 &p_point, const Variant &p_data) {
  716. if (p_point.x > get_timeline()->get_name_limit() && p_point.x < get_size().width - get_timeline()->get_buttons_width()) {
  717. Ref<AudioStream> stream;
  718. Dictionary drag_data = p_data;
  719. if (drag_data.has("type") && String(drag_data["type"]) == "resource") {
  720. stream = drag_data["resource"];
  721. } else if (drag_data.has("type") && String(drag_data["type"]) == "files") {
  722. Vector<String> files = drag_data["files"];
  723. if (files.size() == 1) {
  724. String file = files[0];
  725. stream = ResourceLoader::load(file);
  726. }
  727. }
  728. if (stream.is_valid()) {
  729. int x = p_point.x - get_timeline()->get_name_limit();
  730. float ofs = x / get_timeline()->get_zoom_scale();
  731. ofs += get_timeline()->get_value();
  732. ofs = get_editor()->snap_time(ofs);
  733. while (get_animation()->track_find_key(get_track(), ofs, true) != -1) { //make sure insertion point is valid
  734. ofs += 0.001;
  735. }
  736. get_undo_redo()->create_action(TTR("Add Audio Track Clip"));
  737. get_undo_redo()->add_do_method(get_animation().ptr(), "audio_track_insert_key", get_track(), ofs, stream);
  738. get_undo_redo()->add_undo_method(get_animation().ptr(), "track_remove_key_at_position", get_track(), ofs);
  739. get_undo_redo()->commit_action();
  740. update();
  741. return;
  742. }
  743. }
  744. AnimationTrackEdit::drop_data(p_point, p_data);
  745. }
  746. void AnimationTrackEditTypeAudio::_gui_input(const Ref<InputEvent> &p_event) {
  747. Ref<InputEventMouseMotion> mm = p_event;
  748. if (!len_resizing && mm.is_valid()) {
  749. bool use_hsize_cursor = false;
  750. for (int i = 0; i < get_animation()->track_get_key_count(get_track()); i++) {
  751. Ref<AudioStream> stream = get_animation()->audio_track_get_key_stream(get_track(), i);
  752. if (!stream.is_valid()) {
  753. continue;
  754. }
  755. float start_ofs = get_animation()->audio_track_get_key_start_offset(get_track(), i);
  756. float end_ofs = get_animation()->audio_track_get_key_end_offset(get_track(), i);
  757. float len = stream->get_length();
  758. if (len == 0) {
  759. Ref<AudioStreamPreview> preview = AudioStreamPreviewGenerator::get_singleton()->generate_preview(stream);
  760. float preview_len = preview->get_length();
  761. len = preview_len;
  762. }
  763. len -= end_ofs;
  764. len -= start_ofs;
  765. if (len <= 0.001) {
  766. len = 0.001;
  767. }
  768. if (get_animation()->track_get_key_count(get_track()) > i + 1) {
  769. len = MIN(len, get_animation()->track_get_key_time(get_track(), i + 1) - get_animation()->track_get_key_time(get_track(), i));
  770. }
  771. float ofs = get_animation()->track_get_key_time(get_track(), i);
  772. ofs -= get_timeline()->get_value();
  773. ofs *= get_timeline()->get_zoom_scale();
  774. ofs += get_timeline()->get_name_limit();
  775. int end = ofs + len * get_timeline()->get_zoom_scale();
  776. if (end >= get_timeline()->get_name_limit() && end <= get_size().width - get_timeline()->get_buttons_width() && ABS(mm->get_position().x - end) < 5 * EDSCALE) {
  777. use_hsize_cursor = true;
  778. len_resizing_index = i;
  779. }
  780. }
  781. if (use_hsize_cursor) {
  782. set_default_cursor_shape(CURSOR_HSIZE);
  783. } else {
  784. set_default_cursor_shape(CURSOR_ARROW);
  785. }
  786. }
  787. if (len_resizing && mm.is_valid()) {
  788. len_resizing_rel += mm->get_relative().x;
  789. len_resizing_start = mm->get_shift();
  790. update();
  791. accept_event();
  792. return;
  793. }
  794. Ref<InputEventMouseButton> mb = p_event;
  795. if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && get_default_cursor_shape() == CURSOR_HSIZE) {
  796. len_resizing = true;
  797. len_resizing_start = mb->get_shift();
  798. len_resizing_from_px = mb->get_position().x;
  799. len_resizing_rel = 0;
  800. update();
  801. accept_event();
  802. return;
  803. }
  804. if (len_resizing && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
  805. float ofs_local = -len_resizing_rel / get_timeline()->get_zoom_scale();
  806. if (len_resizing_start) {
  807. float prev_ofs = get_animation()->audio_track_get_key_start_offset(get_track(), len_resizing_index);
  808. get_undo_redo()->create_action(TTR("Change Audio Track Clip Start Offset"));
  809. get_undo_redo()->add_do_method(get_animation().ptr(), "audio_track_set_key_start_offset", get_track(), len_resizing_index, prev_ofs + ofs_local);
  810. get_undo_redo()->add_undo_method(get_animation().ptr(), "audio_track_set_key_start_offset", get_track(), len_resizing_index, prev_ofs);
  811. get_undo_redo()->commit_action();
  812. } else {
  813. float prev_ofs = get_animation()->audio_track_get_key_end_offset(get_track(), len_resizing_index);
  814. get_undo_redo()->create_action(TTR("Change Audio Track Clip End Offset"));
  815. get_undo_redo()->add_do_method(get_animation().ptr(), "audio_track_set_key_end_offset", get_track(), len_resizing_index, prev_ofs + ofs_local);
  816. get_undo_redo()->add_undo_method(get_animation().ptr(), "audio_track_set_key_end_offset", get_track(), len_resizing_index, prev_ofs);
  817. get_undo_redo()->commit_action();
  818. }
  819. len_resizing = false;
  820. len_resizing_index = -1;
  821. update();
  822. accept_event();
  823. return;
  824. }
  825. AnimationTrackEdit::_gui_input(p_event);
  826. }
  827. ////////////////////
  828. /// SUB ANIMATION ///
  829. int AnimationTrackEditTypeAnimation::get_key_height() const {
  830. if (!ObjectDB::get_instance(id)) {
  831. return AnimationTrackEdit::get_key_height();
  832. }
  833. Ref<Font> font = get_theme_font("font", "Label");
  834. return int(font->get_height() * 1.5);
  835. }
  836. Rect2 AnimationTrackEditTypeAnimation::get_key_rect(int p_index, float p_pixels_sec) {
  837. Object *object = ObjectDB::get_instance(id);
  838. if (!object) {
  839. return AnimationTrackEdit::get_key_rect(p_index, p_pixels_sec);
  840. }
  841. AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(object);
  842. if (!ap) {
  843. return AnimationTrackEdit::get_key_rect(p_index, p_pixels_sec);
  844. }
  845. String anim = get_animation()->animation_track_get_key_animation(get_track(), p_index);
  846. if (anim != "[stop]" && ap->has_animation(anim)) {
  847. float len = ap->get_animation(anim)->get_length();
  848. if (get_animation()->track_get_key_count(get_track()) > p_index + 1) {
  849. len = MIN(len, get_animation()->track_get_key_time(get_track(), p_index + 1) - get_animation()->track_get_key_time(get_track(), p_index));
  850. }
  851. return Rect2(0, 0, len * p_pixels_sec, get_size().height);
  852. } else {
  853. Ref<Font> font = get_theme_font("font", "Label");
  854. int fh = font->get_height() * 0.8;
  855. return Rect2(0, 0, fh, get_size().height);
  856. }
  857. }
  858. bool AnimationTrackEditTypeAnimation::is_key_selectable_by_distance() const {
  859. return false;
  860. }
  861. void AnimationTrackEditTypeAnimation::draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right) {
  862. Object *object = ObjectDB::get_instance(id);
  863. if (!object) {
  864. AnimationTrackEdit::draw_key(p_index, p_pixels_sec, p_x, p_selected, p_clip_left, p_clip_right);
  865. return;
  866. }
  867. AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(object);
  868. if (!ap) {
  869. AnimationTrackEdit::draw_key(p_index, p_pixels_sec, p_x, p_selected, p_clip_left, p_clip_right);
  870. return;
  871. }
  872. String anim = get_animation()->animation_track_get_key_animation(get_track(), p_index);
  873. if (anim != "[stop]" && ap->has_animation(anim)) {
  874. float len = ap->get_animation(anim)->get_length();
  875. if (get_animation()->track_get_key_count(get_track()) > p_index + 1) {
  876. len = MIN(len, get_animation()->track_get_key_time(get_track(), p_index + 1) - get_animation()->track_get_key_time(get_track(), p_index));
  877. }
  878. int pixel_len = len * p_pixels_sec;
  879. int pixel_begin = p_x;
  880. int pixel_end = p_x + pixel_len;
  881. if (pixel_end < p_clip_left)
  882. return;
  883. if (pixel_begin > p_clip_right)
  884. return;
  885. int from_x = MAX(pixel_begin, p_clip_left);
  886. int to_x = MIN(pixel_end, p_clip_right);
  887. if (to_x <= from_x)
  888. return;
  889. Ref<Font> font = get_theme_font("font", "Label");
  890. int fh = font->get_height() * 1.5;
  891. Rect2 rect(from_x, int(get_size().height - fh) / 2, to_x - from_x, fh);
  892. Color color = get_theme_color("font_color", "Label");
  893. Color bg = color;
  894. bg.r = 1 - color.r;
  895. bg.g = 1 - color.g;
  896. bg.b = 1 - color.b;
  897. draw_rect(rect, bg);
  898. Vector<Vector2> lines;
  899. Vector<Color> colorv;
  900. {
  901. Ref<Animation> animation = ap->get_animation(anim);
  902. for (int i = 0; i < animation->get_track_count(); i++) {
  903. float h = (rect.size.height - 2) / animation->get_track_count();
  904. int y = 2 + h * i + h / 2;
  905. for (int j = 0; j < animation->track_get_key_count(i); j++) {
  906. float ofs = animation->track_get_key_time(i, j);
  907. int x = p_x + ofs * p_pixels_sec + 2;
  908. if (x < from_x || x >= (to_x - 4))
  909. continue;
  910. lines.push_back(Point2(x, y));
  911. lines.push_back(Point2(x + 1, y));
  912. }
  913. }
  914. colorv.push_back(color);
  915. }
  916. if (lines.size() > 2) {
  917. RS::get_singleton()->canvas_item_add_multiline(get_canvas_item(), lines, colorv);
  918. }
  919. int limit = to_x - from_x - 4;
  920. if (limit > 0) {
  921. draw_string(font, Point2(from_x + 2, int(get_size().height - font->get_height()) / 2 + font->get_ascent()), anim, color);
  922. }
  923. if (p_selected) {
  924. Color accent = get_theme_color("accent_color", "Editor");
  925. draw_rect(rect, accent, false);
  926. }
  927. } else {
  928. Ref<Font> font = get_theme_font("font", "Label");
  929. int fh = font->get_height() * 0.8;
  930. Rect2 rect(Vector2(p_x, int(get_size().height - fh) / 2), Size2(fh, fh));
  931. Color color = get_theme_color("font_color", "Label");
  932. draw_rect(rect, color);
  933. if (p_selected) {
  934. Color accent = get_theme_color("accent_color", "Editor");
  935. draw_rect(rect, accent, false);
  936. }
  937. }
  938. }
  939. void AnimationTrackEditTypeAnimation::set_node(Object *p_object) {
  940. id = p_object->get_instance_id();
  941. }
  942. AnimationTrackEditTypeAnimation::AnimationTrackEditTypeAnimation() {
  943. }
  944. /////////
  945. AnimationTrackEdit *AnimationTrackEditDefaultPlugin::create_value_track_edit(Object *p_object, Variant::Type p_type, const String &p_property, PropertyHint p_hint, const String &p_hint_string, int p_usage) {
  946. if (p_property == "playing" && (p_object->is_class("AudioStreamPlayer") || p_object->is_class("AudioStreamPlayer2D") || p_object->is_class("AudioStreamPlayer3D"))) {
  947. AnimationTrackEditAudio *audio = memnew(AnimationTrackEditAudio);
  948. audio->set_node(p_object);
  949. return audio;
  950. }
  951. if (p_property == "frame" && (p_object->is_class("Sprite2D") || p_object->is_class("Sprite3D") || p_object->is_class("AnimatedSprite2D") || p_object->is_class("AnimatedSprite3D"))) {
  952. AnimationTrackEditSpriteFrame *sprite = memnew(AnimationTrackEditSpriteFrame);
  953. sprite->set_node(p_object);
  954. return sprite;
  955. }
  956. if (p_property == "frame_coords" && (p_object->is_class("Sprite2D") || p_object->is_class("Sprite3D"))) {
  957. AnimationTrackEditSpriteFrame *sprite = memnew(AnimationTrackEditSpriteFrame);
  958. sprite->set_as_coords();
  959. sprite->set_node(p_object);
  960. return sprite;
  961. }
  962. if (p_property == "current_animation" && (p_object->is_class("AnimationPlayer"))) {
  963. AnimationTrackEditSubAnim *player = memnew(AnimationTrackEditSubAnim);
  964. player->set_node(p_object);
  965. return player;
  966. }
  967. if (p_property == "volume_db") {
  968. AnimationTrackEditVolumeDB *vu = memnew(AnimationTrackEditVolumeDB);
  969. return vu;
  970. }
  971. if (p_type == Variant::BOOL) {
  972. return memnew(AnimationTrackEditBool);
  973. }
  974. if (p_type == Variant::COLOR) {
  975. return memnew(AnimationTrackEditColor);
  976. }
  977. return nullptr;
  978. }
  979. AnimationTrackEdit *AnimationTrackEditDefaultPlugin::create_audio_track_edit() {
  980. return memnew(AnimationTrackEditTypeAudio);
  981. }
  982. AnimationTrackEdit *AnimationTrackEditDefaultPlugin::create_animation_track_edit(Object *p_object) {
  983. AnimationTrackEditTypeAnimation *an = memnew(AnimationTrackEditTypeAnimation);
  984. an->set_node(p_object);
  985. return an;
  986. }