SpineSprite.cpp 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039
  1. /******************************************************************************
  2. * Spine Runtimes License Agreement
  3. * Last updated January 1, 2020. Replaces all prior versions.
  4. *
  5. * Copyright (c) 2013-2020, Esoteric Software LLC
  6. *
  7. * Integration of the Spine Runtimes into software or otherwise creating
  8. * derivative works of the Spine Runtimes is permitted under the terms and
  9. * conditions of Section 2 of the Spine Editor License Agreement:
  10. * http://esotericsoftware.com/spine-editor-license
  11. *
  12. * Otherwise, it is permitted to integrate the Spine Runtimes into software
  13. * or otherwise create derivative works of the Spine Runtimes (collectively,
  14. * "Products"), provided that each user of the Products must obtain their own
  15. * Spine Editor license and redistribution of the Products in any form must
  16. * include this license and copyright notice.
  17. *
  18. * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
  19. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
  24. * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. *****************************************************************************/
  29. #include "SpineSprite.h"
  30. #include "SpineTrackEntry.h"
  31. #include "SpineEvent.h"
  32. void SpineSprite::_bind_methods() {
  33. ClassDB::bind_method(D_METHOD("set_animation_state_data_res", "animation_state_data_res"), &SpineSprite::set_animation_state_data_res);
  34. ClassDB::bind_method(D_METHOD("get_animation_state_data_res"), &SpineSprite::get_animation_state_data_res);
  35. ClassDB::bind_method(D_METHOD("_on_animation_data_created"), &SpineSprite::_on_animation_data_created);
  36. ClassDB::bind_method(D_METHOD("get_skeleton"), &SpineSprite::get_skeleton);
  37. ClassDB::bind_method(D_METHOD("get_animation_state"), &SpineSprite::get_animation_state);
  38. ClassDB::bind_method(D_METHOD("_on_animation_data_changed"), &SpineSprite::_on_animation_data_changed);
  39. ClassDB::bind_method(D_METHOD("get_current_animations"), &SpineSprite::get_current_animations);
  40. ClassDB::bind_method(D_METHOD("set_current_animations", "current_animations"), &SpineSprite::set_current_animations);
  41. ClassDB::bind_method(D_METHOD("get_select_track_id"), &SpineSprite::get_select_track_id);
  42. ClassDB::bind_method(D_METHOD("set_select_track_id", "track_id"), &SpineSprite::set_select_track_id);
  43. ClassDB::bind_method(D_METHOD("get_clear_track"), &SpineSprite::get_clear_track);
  44. ClassDB::bind_method(D_METHOD("set_clear_track", "v"), &SpineSprite::set_clear_track);
  45. ClassDB::bind_method(D_METHOD("get_clear_tracks"), &SpineSprite::get_clear_tracks);
  46. ClassDB::bind_method(D_METHOD("set_clear_tracks", "v"), &SpineSprite::set_clear_tracks);
  47. ClassDB::bind_method(D_METHOD("get_empty_animation_duration"), &SpineSprite::get_empty_animation_duration);
  48. ClassDB::bind_method(D_METHOD("set_empty_animation_duration", "track_id"), &SpineSprite::set_empty_animation_duration);
  49. ClassDB::bind_method(D_METHOD("get_set_empty_animation"), &SpineSprite::get_set_empty_animation);
  50. ClassDB::bind_method(D_METHOD("set_set_empty_animation", "v"), &SpineSprite::set_set_empty_animation);
  51. ClassDB::bind_method(D_METHOD("get_set_empty_animations"), &SpineSprite::get_set_empty_animations);
  52. ClassDB::bind_method(D_METHOD("set_set_empty_animations", "v"), &SpineSprite::set_set_empty_animations);
  53. ClassDB::bind_method(D_METHOD("get_bind_slot_nodes"), &SpineSprite::get_bind_slot_nodes);
  54. ClassDB::bind_method(D_METHOD("set_bind_slot_nodes", "v"), &SpineSprite::set_bind_slot_nodes);
  55. ClassDB::bind_method(D_METHOD("get_overlap"), &SpineSprite::get_overlap);
  56. ClassDB::bind_method(D_METHOD("set_overlap", "v"), &SpineSprite::set_overlap);
  57. ClassDB::bind_method(D_METHOD("set_skin", "v"), &SpineSprite::set_skin);
  58. ClassDB::bind_method(D_METHOD("get_skin"), &SpineSprite::get_skin);
  59. ClassDB::bind_method(D_METHOD("_on_skin_property_changed"), &SpineSprite::_on_skin_property_changed);
  60. ClassDB::bind_method(D_METHOD("gen_spine_skin_from_packed_resource", "res"), &SpineSprite::gen_spine_skin_from_packed_resource);
  61. ClassDB::bind_method(D_METHOD("bone_get_global_transform", "bone_name"), &SpineSprite::bone_get_global_transform);
  62. ClassDB::bind_method(D_METHOD("bone_set_global_transform", "bone_name", "global_transform"), &SpineSprite::bone_set_global_transform);
  63. ClassDB::bind_method(D_METHOD("set_process_mode", "v"), &SpineSprite::set_process_mode);
  64. ClassDB::bind_method(D_METHOD("get_process_mode"), &SpineSprite::get_process_mode);
  65. ClassDB::bind_method(D_METHOD("manual_update", "delta"), &SpineSprite::_update_all);
  66. ADD_SIGNAL(MethodInfo("animation_state_ready", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "skeleton", PROPERTY_HINT_TYPE_STRING, "SpineSkeleton")));
  67. ADD_SIGNAL(MethodInfo("animation_start", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent")));
  68. ADD_SIGNAL(MethodInfo("animation_interrupt", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent")));
  69. ADD_SIGNAL(MethodInfo("animation_end", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent")));
  70. ADD_SIGNAL(MethodInfo("animation_complete", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent")));
  71. ADD_SIGNAL(MethodInfo("animation_dispose", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent")));
  72. ADD_SIGNAL(MethodInfo("animation_event", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent")));
  73. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "animation_state_data_res", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineAnimationStateDataResource"), "set_animation_state_data_res", "get_animation_state_data_res");
  74. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "overlap"), "set_overlap", "get_overlap");
  75. ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "bind_slot_nodes"), "set_bind_slot_nodes", "get_bind_slot_nodes");
  76. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "packed_skin_resource", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "PackedSpineSkinResource"), "set_skin", "get_skin");
  77. ADD_GROUP("animation", "");
  78. ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Process,Physics,Manually"), "set_process_mode", "get_process_mode");
  79. ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "current_animations"), "set_current_animations", "get_current_animations");
  80. BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Process);
  81. BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Physics);
  82. BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Manual);
  83. }
  84. SpineSprite::SpineSprite() :
  85. select_track_id(0), empty_animation_duration(0.2f), skeleton_clipper(NULL),
  86. overlap(false),
  87. process_mode(ProcessMode_Process)
  88. {
  89. skeleton_clipper = new spine::SkeletonClipping();
  90. }
  91. SpineSprite::~SpineSprite() {
  92. delete skeleton_clipper;
  93. }
  94. void SpineSprite::_notification(int p_what) {
  95. switch (p_what) {
  96. case NOTIFICATION_READY:{
  97. set_process_internal(process_mode == ProcessMode_Process);
  98. set_physics_process_internal(process_mode == ProcessMode_Physics);
  99. remove_redundant_mesh_instances();
  100. } break;
  101. case NOTIFICATION_INTERNAL_PROCESS: {
  102. if (process_mode == ProcessMode_Process)
  103. _update_all(get_process_delta_time());
  104. } break;
  105. case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
  106. if (process_mode == ProcessMode_Physics)
  107. _update_all(get_physics_process_delta_time());
  108. } break;
  109. }
  110. }
  111. void SpineSprite::_update_all(float delta) {
  112. if (!(skeleton.is_valid() && animation_state.is_valid()) || mesh_instances.empty())
  113. return;
  114. animation_state->update(delta);
  115. if (!is_visible_in_tree())
  116. return;
  117. animation_state->apply(skeleton);
  118. skeleton->update_world_transform();
  119. update_mesh_from_skeleton(skeleton);
  120. update();
  121. update_bind_slot_nodes();
  122. }
  123. void SpineSprite::update_bind_slot_nodes(){
  124. if(animation_state.is_valid() && skeleton.is_valid()){
  125. for(size_t i=0, n=bind_slot_nodes.size(); i<n; ++i){
  126. auto a = bind_slot_nodes[i];
  127. if(a.get_type() == Variant::DICTIONARY){
  128. auto d = (Dictionary) a;
  129. if(d.has("slot_name") && d.has("node_path")){
  130. NodePath node_path = d["node_path"];
  131. Node *node = get_node_or_null(node_path);
  132. if(node && node->is_class("Node2D")){
  133. Node2D *node2d = (Node2D*) node;
  134. String slot_name = d["slot_name"];
  135. auto slot = skeleton->find_slot(slot_name);
  136. if(slot.is_valid()){
  137. auto bone = slot->get_bone();
  138. if(bone.is_valid())
  139. {
  140. update_bind_slot_node_transform(bone, node2d);
  141. update_bind_slot_node_draw_order(slot_name, node2d);
  142. }
  143. }
  144. }
  145. }
  146. }else if(a.get_type() == Variant::ARRAY){
  147. auto as = (Array) a;// 0: slot_name, 1: node_path
  148. if(as.size() >= 2 && as[0].get_type() == Variant::STRING && as[1].get_type() == Variant::NODE_PATH){
  149. NodePath node_path = as[1];
  150. Node *node = get_node_or_null(node_path);
  151. if(node && node->is_class("Node2D")){
  152. Node2D *node2d = (Node2D*) node;
  153. String slot_name = as[0];
  154. auto slot = skeleton->find_slot(slot_name);
  155. if(slot.is_valid()){
  156. auto bone = slot->get_bone();
  157. if(bone.is_valid())
  158. {
  159. update_bind_slot_node_transform(bone, node2d);
  160. update_bind_slot_node_draw_order(slot_name, node2d);
  161. }
  162. }
  163. }
  164. }
  165. }
  166. }
  167. }
  168. }
  169. void SpineSprite::update_bind_slot_node_transform(Ref<SpineBone> bone, Node2D *node2d){
  170. bone->apply_world_transform_2d(node2d);
  171. }
  172. void SpineSprite::update_bind_slot_node_draw_order(const String &slot_name, Node2D *node2d){
  173. auto mesh_ins = find_node(slot_name);
  174. if(mesh_ins){
  175. auto pos = mesh_ins->get_index();
  176. // get child
  177. auto node = find_child_node_by_node(node2d);
  178. if(node && node->get_index() != pos+1){
  179. move_child(node, pos+1);
  180. }
  181. }
  182. }
  183. Node *SpineSprite::find_child_node_by_node(Node *node){
  184. if(node == NULL) return NULL;
  185. while(node && node->get_parent() != this) node = node->get_parent();
  186. return node;
  187. }
  188. void SpineSprite::set_animation_state_data_res(const Ref<SpineAnimationStateDataResource> &s) {
  189. animation_state_data_res = s;
  190. // update run time skeleton and meshes
  191. _on_animation_data_changed();
  192. }
  193. Ref<SpineAnimationStateDataResource> SpineSprite::get_animation_state_data_res() {
  194. return animation_state_data_res;
  195. }
  196. void SpineSprite::_on_animation_data_created(){
  197. // print_line("_on_animation_data_created");
  198. skeleton = Ref<SpineSkeleton>(memnew(SpineSkeleton));
  199. skeleton->load_skeleton(animation_state_data_res->get_skeleton());
  200. skeleton->set_spine_sprite(this);
  201. // print_line("Run time skeleton created.");
  202. animation_state = Ref<SpineAnimationState>(memnew(SpineAnimationState));
  203. animation_state->load_animation_state(animation_state_data_res);
  204. animation_state->get_animation_state()->setListener(this);
  205. // print_line("Run time animation state created.");
  206. // add mesh instances related by current skeleton
  207. animation_state->update(0);
  208. animation_state->apply(skeleton);
  209. skeleton->update_world_transform();
  210. gen_mesh_from_skeleton(skeleton);
  211. if (process_mode == ProcessMode_Process) {
  212. _notification(NOTIFICATION_INTERNAL_PROCESS);
  213. } else if (process_mode == ProcessMode_Physics) {
  214. _notification(NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
  215. }
  216. emit_signal("animation_state_ready", animation_state, skeleton);
  217. }
  218. void SpineSprite::_on_animation_data_changed() {
  219. // print_line("_on_animation_data_changed");
  220. remove_mesh_instances();
  221. skeleton.unref();
  222. animation_state.unref();
  223. if(!animation_state_data_res.is_null())
  224. {
  225. if(!animation_state_data_res->is_connected("animation_state_data_created", this, "_on_animation_data_created"))
  226. animation_state_data_res->connect("animation_state_data_created", this, "_on_animation_data_created");
  227. if(!animation_state_data_res->is_connected("skeleton_data_res_changed", this, "_on_animation_data_changed"))
  228. animation_state_data_res->connect("skeleton_data_res_changed", this, "_on_animation_data_changed");
  229. if(!animation_state_data_res->is_connected("animation_state_data_changed", this, "_on_animation_data_changed"))
  230. animation_state_data_res->connect("animation_state_data_changed", this, "_on_animation_data_changed");
  231. if(animation_state_data_res->is_animation_state_data_created())
  232. {
  233. _on_animation_data_created();
  234. }
  235. }
  236. }
  237. Ref<SpineSkeleton> SpineSprite::get_skeleton() {
  238. return skeleton;
  239. }
  240. Ref<SpineAnimationState> SpineSprite::get_animation_state() {
  241. return animation_state;
  242. }
  243. void SpineSprite::gen_mesh_from_skeleton(Ref<SpineSkeleton> s) {
  244. auto sk = s->get_spine_object();
  245. for(size_t i=0, n = sk->getSlots().size(); i < n; ++i)
  246. {
  247. // creat a mesh instance 2d for every slot
  248. auto mesh_ins = memnew(SpineSpriteMeshInstance2D);
  249. add_child(mesh_ins);
  250. mesh_ins->set_position(Vector2(0, 0));
  251. mesh_ins->set_owner(this);
  252. mesh_instances.push_back(mesh_ins);
  253. spine::Slot *slot = sk->getDrawOrder()[i];
  254. mesh_ins->set_name(slot->getData().getName().buffer());
  255. Ref<SpineSlot> gd_slot(memnew(SpineSlot));
  256. gd_slot->set_spine_object(slot);
  257. mesh_ins->set_slot(gd_slot);
  258. // creat a material
  259. Ref<CanvasItemMaterial> mat(memnew(CanvasItemMaterial));
  260. CanvasItemMaterial::BlendMode blend_mode;
  261. switch (slot->getData().getBlendMode()) {
  262. case spine::BlendMode_Normal:
  263. blend_mode = CanvasItemMaterial::BLEND_MODE_MIX;
  264. break;
  265. case spine::BlendMode_Additive:
  266. blend_mode = CanvasItemMaterial::BLEND_MODE_ADD;
  267. break;
  268. case spine::BlendMode_Multiply:
  269. blend_mode = CanvasItemMaterial::BLEND_MODE_MUL;
  270. break;
  271. case spine::BlendMode_Screen:
  272. blend_mode = CanvasItemMaterial::BLEND_MODE_MIX;
  273. break;
  274. default:
  275. blend_mode = CanvasItemMaterial::BLEND_MODE_MIX;
  276. }
  277. mat->set_blend_mode(blend_mode);
  278. mesh_ins->set_material(mat);
  279. }
  280. }
  281. void SpineSprite::remove_mesh_instances() {
  282. for(size_t i=0;i < mesh_instances.size();++i)
  283. {
  284. remove_child(mesh_instances[i]);
  285. memdelete(mesh_instances[i]);
  286. }
  287. mesh_instances.clear();
  288. }
  289. void SpineSprite::remove_redundant_mesh_instances() {
  290. Vector<Node*> ms;
  291. // remove the redundant mesh instances that added by duplicating
  292. // print_line("start clearing");
  293. for(size_t i=0, n=get_child_count(); i<n; ++i){
  294. auto node = get_child(i);
  295. // print_line(String("get a node: ") + node->get_name());
  296. if(node && node->is_class("SpineSpriteMeshInstance2D")){
  297. if(mesh_instances.find((SpineSpriteMeshInstance2D*)node) == -1)
  298. {
  299. // print_line("marked clear");
  300. ms.push_back(node);
  301. }
  302. }
  303. }
  304. for(size_t i=0, n=ms.size(); i<n; ++i){
  305. remove_child(ms[i]);
  306. memdelete(ms[i]);
  307. }
  308. ms.clear();
  309. // print_line("end clearing");
  310. }
  311. #define TEMP_COPY(t, get_res) do{auto &temp_uvs = get_res; \
  312. t.setSize(temp_uvs.size(), 0); \
  313. for(size_t j=0;j<t.size();++j) \
  314. { \
  315. t[j] = temp_uvs[j]; \
  316. }}while(false);
  317. void SpineSprite::update_mesh_from_skeleton(Ref<SpineSkeleton> s) {
  318. static const unsigned short VERTEX_STRIDE = 2;
  319. static const unsigned short UV_STRIDE = 2;
  320. static unsigned short quad_indices[] = { 0, 1, 2, 2, 3, 0 };
  321. auto sk = s->get_spine_object();
  322. for(size_t i=0, n = sk->getSlots().size(); i < n; ++i)
  323. {
  324. spine::Vector<float> vertices;
  325. spine::Vector<float> uvs;
  326. spine::Vector<unsigned short> indices;
  327. spine::Slot *slot = sk->getDrawOrder()[i];
  328. spine::Attachment *attachment = slot->getAttachment();
  329. if(!attachment){
  330. // set invisible to mesh instance
  331. mesh_instances[i]->set_visible(false);
  332. skeleton_clipper->clipEnd(*slot);
  333. continue;
  334. }
  335. mesh_instances[i]->set_visible(true);
  336. spine::Color skeleton_color = sk->getColor();
  337. spine::Color slot_color = slot->getColor();
  338. spine::Color tint(skeleton_color.r * slot_color.r, skeleton_color.g * slot_color.g, skeleton_color.b * slot_color.b, skeleton_color.a * slot_color.a);
  339. Ref<Texture> tex;
  340. Ref<Texture> normal_tex;
  341. size_t v_num = 0;
  342. if(attachment->getRTTI().isExactly(spine::RegionAttachment::rtti))
  343. {
  344. spine::RegionAttachment *region_attachment = (spine::RegionAttachment*)attachment;
  345. auto p_spine_renderer_object = (SpineRendererObject*) ((spine::AtlasRegion*)region_attachment->getRendererObject())->page->getRendererObject();
  346. tex = p_spine_renderer_object->tex;
  347. normal_tex = p_spine_renderer_object->normal_tex;
  348. v_num = 4;
  349. vertices.setSize(v_num * VERTEX_STRIDE, 0);
  350. region_attachment->computeWorldVertices(slot->getBone(), vertices, 0);
  351. TEMP_COPY(uvs, region_attachment->getUVs());
  352. indices.setSize(sizeof(quad_indices) / sizeof(unsigned short), 0);
  353. for (size_t j = 0, qn = indices.size();j<qn;++j) {
  354. indices[j] = quad_indices[j];
  355. }
  356. auto attachment_color = region_attachment->getColor();
  357. tint.r *= attachment_color.r;
  358. tint.g *= attachment_color.g;
  359. tint.b *= attachment_color.b;
  360. tint.a *= attachment_color.a;
  361. }else if(attachment->getRTTI().isExactly(spine::MeshAttachment::rtti)) {
  362. spine::MeshAttachment *mesh = (spine::MeshAttachment*) attachment;
  363. auto p_spine_renderer_object = (SpineRendererObject*) ((spine::AtlasRegion*)mesh->getRendererObject())->page->getRendererObject();
  364. tex = p_spine_renderer_object->tex;
  365. normal_tex = p_spine_renderer_object->normal_tex;
  366. v_num = mesh->getWorldVerticesLength()/VERTEX_STRIDE;
  367. vertices.setSize(mesh->getWorldVerticesLength(), 0);
  368. mesh->computeWorldVertices(*slot, vertices);
  369. // uvs = mesh->getUVs();
  370. // indices = mesh->getTriangles();
  371. TEMP_COPY(uvs, mesh->getUVs());
  372. TEMP_COPY(indices, mesh->getTriangles());
  373. auto attachment_color = mesh->getColor();
  374. tint.r *= attachment_color.r;
  375. tint.g *= attachment_color.g;
  376. tint.b *= attachment_color.b;
  377. tint.a *= attachment_color.a;
  378. } else if (attachment->getRTTI().isExactly(spine::ClippingAttachment::rtti)) {
  379. auto clip = (spine::ClippingAttachment *) attachment;
  380. skeleton_clipper->clipStart(*slot, clip);
  381. continue;
  382. } else {
  383. skeleton_clipper->clipEnd(*slot);
  384. continue;
  385. }
  386. auto mesh_ins = mesh_instances[i];
  387. VisualServer::get_singleton()->canvas_item_clear(mesh_ins->get_canvas_item());
  388. if (skeleton_clipper->isClipping()) {
  389. skeleton_clipper->clipTriangles(vertices, indices, uvs, VERTEX_STRIDE);
  390. if (skeleton_clipper->getClippedTriangles().size() == 0) {
  391. skeleton_clipper->clipEnd(*slot);
  392. continue;
  393. }
  394. auto &clipped_vertices = skeleton_clipper->getClippedVertices();
  395. v_num = clipped_vertices.size()/VERTEX_STRIDE;
  396. auto &clipped_uvs = skeleton_clipper->getClippedUVs();
  397. auto &clipped_indices = skeleton_clipper->getClippedTriangles();
  398. if (indices.size() > 0) {
  399. Vector<Vector2> p_points, p_uvs;
  400. Vector<Color> p_colors;
  401. Vector<int> p_indices;
  402. p_points.resize(v_num);
  403. p_uvs.resize(v_num);
  404. p_colors.resize(v_num);
  405. for (size_t j = 0; j < v_num; j++) {
  406. p_points.set(j, Vector2(clipped_vertices[j*VERTEX_STRIDE], -clipped_vertices[j*VERTEX_STRIDE+1]));
  407. p_uvs.set(j, Vector2(clipped_uvs[j*VERTEX_STRIDE], clipped_uvs[j*VERTEX_STRIDE+1]));
  408. p_colors.set(j, Color(tint.r, tint.g, tint.b, tint.a));
  409. }
  410. p_indices.resize(clipped_indices.size());
  411. for (size_t j = 0; j < clipped_indices.size(); ++j) {
  412. p_indices.set(j, clipped_indices[j]);
  413. }
  414. VisualServer::get_singleton()->canvas_item_add_triangle_array(mesh_ins->get_canvas_item(),
  415. p_indices,
  416. p_points,
  417. p_colors,
  418. p_uvs,
  419. Vector<int>(),
  420. Vector<float>(),
  421. tex.is_null() ? RID() : tex->get_rid(),
  422. -1,
  423. normal_tex.is_null() ? RID() : normal_tex->get_rid());
  424. }
  425. }else {
  426. if (indices.size() > 0) {
  427. Vector<Vector2> p_points, p_uvs;
  428. Vector<Color> p_colors;
  429. Vector<int> p_indices;
  430. p_points.resize(v_num);
  431. p_uvs.resize(v_num);
  432. p_colors.resize(v_num);
  433. for (size_t j = 0; j < v_num; j++) {
  434. p_points.set(j, Vector2(vertices[j*VERTEX_STRIDE], -vertices[j*VERTEX_STRIDE+1]));
  435. p_uvs.set(j, Vector2(uvs[j*VERTEX_STRIDE], uvs[j*VERTEX_STRIDE+1]));
  436. p_colors.set(j, Color(tint.r, tint.g, tint.b, tint.a));
  437. }
  438. p_indices.resize(indices.size());
  439. for (size_t j = 0; j < indices.size(); ++j) {
  440. p_indices.set(j, indices[j]);
  441. }
  442. VisualServer::get_singleton()->canvas_item_add_triangle_array(mesh_ins->get_canvas_item(),
  443. p_indices,
  444. p_points,
  445. p_colors,
  446. p_uvs,
  447. Vector<int>(),
  448. Vector<float>(),
  449. tex.is_null() ? RID() : tex->get_rid(),
  450. -1,
  451. normal_tex.is_null() ? RID() : normal_tex->get_rid());
  452. }
  453. }
  454. skeleton_clipper->clipEnd(*slot);
  455. if (mesh_ins->get_material()->is_class("CanvasItemMaterial")){
  456. Ref<CanvasItemMaterial> mat = mesh_ins->get_material();
  457. CanvasItemMaterial::BlendMode blend_mode;
  458. switch (slot->getData().getBlendMode()) {
  459. case spine::BlendMode_Normal:
  460. blend_mode = CanvasItemMaterial::BLEND_MODE_MIX;
  461. break;
  462. case spine::BlendMode_Additive:
  463. blend_mode = CanvasItemMaterial::BLEND_MODE_ADD;
  464. break;
  465. case spine::BlendMode_Multiply:
  466. blend_mode = CanvasItemMaterial::BLEND_MODE_MUL;
  467. break;
  468. case spine::BlendMode_Screen:
  469. blend_mode = CanvasItemMaterial::BLEND_MODE_MIX;
  470. break;
  471. default:
  472. blend_mode = CanvasItemMaterial::BLEND_MODE_MIX;
  473. }
  474. mat->set_blend_mode(blend_mode);
  475. }
  476. }
  477. skeleton_clipper->clipEnd();
  478. }
  479. void SpineSprite::callback(spine::AnimationState *state, spine::EventType type, spine::TrackEntry *entry, spine::Event *event) {
  480. Ref<SpineTrackEntry> gd_entry(NULL);
  481. Ref<SpineEvent> gd_event(NULL);
  482. if(entry){
  483. gd_entry = Ref<SpineTrackEntry>(memnew(SpineTrackEntry));
  484. gd_entry->set_spine_object(entry);
  485. }
  486. if(event){
  487. gd_event = Ref<SpineEvent>(memnew(SpineEvent));
  488. gd_event->set_spine_object(event);
  489. }
  490. switch (type) {
  491. case spine::EventType_Start:
  492. {
  493. emit_signal("animation_start", animation_state, gd_entry, gd_event);
  494. }break;
  495. case spine::EventType_Interrupt:
  496. {
  497. emit_signal("animation_interrupt", animation_state, gd_entry, gd_event);
  498. }break;
  499. case spine::EventType_End:
  500. {
  501. emit_signal("animation_end", animation_state, gd_entry, gd_event);
  502. }break;
  503. case spine::EventType_Complete:
  504. {
  505. emit_signal("animation_complete", animation_state, gd_entry, gd_event);
  506. }break;
  507. case spine::EventType_Dispose:
  508. {
  509. emit_signal("animation_dispose", animation_state, gd_entry, gd_event);
  510. }break;
  511. case spine::EventType_Event:
  512. {
  513. emit_signal("animation_event", animation_state, gd_entry, gd_event);
  514. }break;
  515. }
  516. }
  517. // External feature functions
  518. Array SpineSprite::get_current_animations() {
  519. return current_animations.duplicate(true);
  520. }
  521. void SpineSprite::set_current_animations(Array as) {
  522. current_animations = as.duplicate(true);
  523. // validate it then play the animations
  524. _validate_and_play_current_animations();
  525. }
  526. int SpineSprite::get_select_track_id(){
  527. return select_track_id;
  528. }
  529. void SpineSprite::set_select_track_id(int v){
  530. select_track_id = v;
  531. if(select_track_id < 0) select_track_id = 0;
  532. }
  533. bool SpineSprite::get_clear_track(){
  534. return false;
  535. }
  536. void SpineSprite::set_clear_track(bool v){
  537. if(v && animation_state.is_valid() && skeleton.is_valid())
  538. animation_state->clear_track(select_track_id);
  539. }
  540. bool SpineSprite::get_clear_tracks(){
  541. return false;
  542. }
  543. void SpineSprite::set_clear_tracks(bool v){
  544. if(v && animation_state.is_valid() && skeleton.is_valid())
  545. animation_state->clear_tracks();
  546. }
  547. float SpineSprite::get_empty_animation_duration(){
  548. return empty_animation_duration;
  549. }
  550. void SpineSprite::set_empty_animation_duration(float v){
  551. empty_animation_duration = v;
  552. }
  553. bool SpineSprite::get_set_empty_animation(){
  554. return false;
  555. }
  556. void SpineSprite::set_set_empty_animation(bool v){
  557. if(v && animation_state.is_valid() && skeleton.is_valid())
  558. animation_state->set_empty_animation(select_track_id, empty_animation_duration);
  559. }
  560. bool SpineSprite::get_set_empty_animations(){
  561. return false;
  562. }
  563. void SpineSprite::set_set_empty_animations(bool v){
  564. if(v && animation_state.is_valid() && skeleton.is_valid())
  565. animation_state->set_empty_animations(empty_animation_duration);
  566. }
  567. Array SpineSprite::get_bind_slot_nodes(){
  568. return bind_slot_nodes;
  569. }
  570. void SpineSprite::set_bind_slot_nodes(Array v) {
  571. bind_slot_nodes = v;
  572. }
  573. bool SpineSprite::get_overlap(){
  574. return overlap;
  575. }
  576. void SpineSprite::set_overlap(bool v){
  577. overlap = v;
  578. }
  579. void SpineSprite::set_skin(Ref<PackedSpineSkinResource> v)
  580. {
  581. if(v != skin && skin.is_valid()){
  582. if(skin->is_connected("property_changed", this, "_on_skin_property_changed"))
  583. skin->disconnect("property_changed", this, "_on_skin_property_changed");
  584. }
  585. skin = v;
  586. if(skin.is_valid()){
  587. if(!skin->is_connected("property_changed", this, "_on_skin_property_changed"))
  588. skin->connect("property_changed", this, "_on_skin_property_changed");
  589. update_runtime_skin();
  590. }
  591. }
  592. Ref<PackedSpineSkinResource> SpineSprite::get_skin(){
  593. return skin;
  594. }
  595. void SpineSprite::update_runtime_skin(){
  596. auto new_skin = gen_spine_skin_from_packed_resource(skin);
  597. if(new_skin.is_valid())
  598. {
  599. skeleton->set_skin(new_skin);
  600. skeleton->set_to_setup_pose();
  601. }
  602. }
  603. void SpineSprite::_on_skin_property_changed(){
  604. update_runtime_skin();
  605. }
  606. Ref<SpineSkin> SpineSprite::gen_spine_skin_from_packed_resource(Ref<PackedSpineSkinResource> res){
  607. if(!(animation_state.is_valid() && skeleton.is_valid()))
  608. return NULL;
  609. if(!res.is_valid())
  610. return NULL;
  611. if(res->get_skin_name().empty())
  612. return NULL;
  613. auto exist_skin = animation_state_data_res->get_skeleton()->find_skin(res->get_skin_name());
  614. if(exist_skin.is_valid())
  615. {
  616. return exist_skin;
  617. }
  618. auto new_skin = Ref<SpineSkin>(memnew(SpineSkin))->init(res->get_skin_name());
  619. auto sub_skin_names = res->get_sub_skin_names();
  620. for(size_t i=0;i<sub_skin_names.size();++i)
  621. {
  622. auto skin_name = (String)sub_skin_names[i];
  623. auto sub_skin = animation_state_data_res->get_skeleton()->find_skin(skin_name);
  624. if(sub_skin.is_valid())
  625. new_skin->add_skin(sub_skin);
  626. }
  627. return new_skin;
  628. }
  629. void SpineSprite::bind_slot_with_node_2d(const String &slot_name, Node2D *n){
  630. auto node_path = n->get_path_to(this);
  631. // check if has the same binding
  632. for(size_t i=0, size=bind_slot_nodes.size(); i<size; ++i){
  633. auto a = bind_slot_nodes[i];
  634. if(a.get_type() == Variant::DICTIONARY){
  635. auto d = (Dictionary) a;
  636. if(d.has("slot_name") && d.has("node_path")){
  637. if(slot_name == d["slot_name"] && node_path == d["node_path"]){
  638. return;
  639. }
  640. }
  641. }else if(a.get_type() == Variant::ARRAY){
  642. auto as = (Array) a;
  643. if(as.size() >= 2 && as[0].get_type() == Variant::STRING && as[1].get_type() == Variant::NODE_PATH){
  644. if(slot_name == as[0] && node_path == as[1]){
  645. return;
  646. }
  647. }
  648. }
  649. }
  650. Array bound;
  651. bound.resize(2);
  652. bound[0] = slot_name;
  653. bound[1] = node_path;
  654. bind_slot_nodes.append(bound);
  655. }
  656. void SpineSprite::unbind_slot_with_node_2d(const String &slot_name, Node2D *n){
  657. auto node_path = n->get_path_to(this);
  658. for(size_t i=0, size=bind_slot_nodes.size(); i<size; ++i){
  659. auto a = bind_slot_nodes[i];
  660. if(a.get_type() == Variant::DICTIONARY){
  661. auto d = (Dictionary) a;
  662. if(d.has("slot_name") && d.has("node_path")){
  663. if(slot_name == d["slot_name"] && node_path == d["node_path"]){
  664. bind_slot_nodes.remove(i);
  665. return;
  666. }
  667. }
  668. }else if(a.get_type() == Variant::ARRAY){
  669. auto as = (Array) a;
  670. if(as.size() >= 2 && as[0].get_type() == Variant::STRING && as[1].get_type() == Variant::NODE_PATH){
  671. if(slot_name == as[0] && node_path == as[1]){
  672. bind_slot_nodes.remove(i);
  673. return;
  674. }
  675. }
  676. }
  677. }
  678. }
  679. Transform2D SpineSprite::bone_get_global_transform(const String &bone_name) {
  680. if (!animation_state.is_valid() && !skeleton.is_valid()) {
  681. return get_global_transform();
  682. }
  683. auto bone = skeleton->find_bone(bone_name);
  684. if (!bone.is_valid()) {
  685. print_error(vformat("Bone: '%s' not found.", bone_name));
  686. return get_global_transform();
  687. }
  688. return bone->get_godot_global_transform();
  689. }
  690. void SpineSprite::bone_set_global_transform(const String &bone_name, Transform2D transform) {
  691. if (!animation_state.is_valid() && !skeleton.is_valid()) {
  692. return;
  693. }
  694. auto bone = skeleton->find_bone(bone_name);
  695. if (!bone.is_valid()) {
  696. return;
  697. }
  698. bone->set_godot_global_transform(transform);
  699. }
  700. SpineSprite::ProcessMode SpineSprite::get_process_mode() {
  701. return process_mode;
  702. }
  703. void SpineSprite::set_process_mode(SpineSprite::ProcessMode v) {
  704. process_mode = v;
  705. set_process_internal(process_mode == ProcessMode_Process);
  706. set_physics_process_internal(process_mode == ProcessMode_Physics);
  707. }
  708. void SpineSprite::_get_property_list(List<PropertyInfo> *p_list) const {
  709. p_list->push_back(PropertyInfo(Variant::NIL, "Current Animation Editor", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_CATEGORY));
  710. p_list->push_back(PropertyInfo(Variant::BOOL, "setup_pose_trigger", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
  711. p_list->push_back(PropertyInfo(Variant::BOOL, "clear_tracks_trigger", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
  712. p_list->push_back(PropertyInfo(Variant::BOOL, "set_empty_animations_trigger", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
  713. p_list->push_back(PropertyInfo(Variant::REAL, "empty_animation_duration"));
  714. p_list->push_back(PropertyInfo(Variant::INT, "track_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
  715. for (size_t i=0; i<current_animations.size(); ++i) {
  716. String prefix = vformat("ca/%d/", (unsigned int)i);
  717. p_list->push_back(PropertyInfo(Variant::NIL, vformat("ID %d", (unsigned int)i), PROPERTY_HINT_NONE, prefix, PROPERTY_USAGE_GROUP));
  718. p_list->push_back(PropertyInfo(Variant::INT, vformat("%strack_id", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
  719. Vector<String> anim_list;
  720. if (skeleton.is_valid() && skeleton->get_data().is_valid()) {
  721. skeleton->get_data()->get_animation_names(anim_list);
  722. }
  723. if (anim_list.empty()) anim_list.push_back("No Animation");
  724. p_list->push_back(PropertyInfo(Variant::STRING, vformat("%sanimation", prefix), PROPERTY_HINT_ENUM, String(",").join(anim_list), PROPERTY_USAGE_EDITOR));
  725. p_list->push_back(PropertyInfo(Variant::REAL, vformat("%sdelay", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
  726. p_list->push_back(PropertyInfo(Variant::BOOL, vformat("%sloop", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
  727. p_list->push_back(PropertyInfo(Variant::BOOL, vformat("%sempty", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
  728. p_list->push_back(PropertyInfo(Variant::REAL, vformat("%sempty_animation_duration", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
  729. p_list->push_back(PropertyInfo(Variant::BOOL, vformat("%sclear", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
  730. }
  731. }
  732. bool SpineSprite::_get(const StringName &p_property, Variant &r_value) const {
  733. if (p_property == "setup_pose_trigger" || p_property == "clear_tracks_trigger" || p_property == "set_empty_animations_trigger") {
  734. r_value = false;
  735. return true;
  736. }
  737. if (p_property == "empty_animation_duration") {
  738. r_value = empty_animation_duration;
  739. return true;
  740. }
  741. if (p_property == "track_count") {
  742. r_value = get_current_animation_count();
  743. return true;
  744. }
  745. String p = p_property;
  746. if (p.size() > 2 && p[0] == 'c' && p[1] == 'a' && p[2] == '/') {
  747. Vector<String> sp = p.split("/");
  748. if (sp.size() > 2) {
  749. int64_t id = sp[1].to_int64();
  750. if (id >= 0 && id < current_animations.size()) {
  751. auto &key = sp[2];
  752. if (current_animations[id].get_type() == Variant::DICTIONARY) {
  753. Dictionary dic = current_animations.get(id);
  754. if (dic.has(key)) {
  755. r_value = dic[key];
  756. } else {
  757. if (key == "track_id") r_value = 0;
  758. else if (key == "animation") r_value = "";
  759. else if (key == "loop") r_value = true;
  760. else if (key == "empty") r_value = false;
  761. else if (key == "empty_animation_duration") r_value = 0.3;
  762. else if (key == "clear") r_value = false;
  763. else if (key == "delay") r_value = 0;
  764. else return false;
  765. }
  766. return true;
  767. }
  768. }
  769. }
  770. }
  771. return false;
  772. }
  773. bool SpineSprite::_set(const StringName &p_property, const Variant &p_value) {
  774. if (p_property == "setup_pose_trigger") {
  775. if (p_value) {
  776. if (skeleton.is_valid()) {
  777. skeleton->set_bones_to_setup_pose();
  778. skeleton->set_slots_to_setup_pose();
  779. }
  780. }
  781. return true;
  782. }
  783. if (p_property == "clear_tracks_trigger") {
  784. if (p_value) {
  785. if (animation_state.is_valid() && skeleton.is_valid()) {
  786. animation_state->clear_tracks();
  787. }
  788. }
  789. return true;
  790. }
  791. if (p_property == "set_empty_animations_trigger") {
  792. if (p_value) {
  793. if (animation_state.is_valid() && skeleton.is_valid()) {
  794. animation_state->set_empty_animations(empty_animation_duration);
  795. }
  796. }
  797. return true;
  798. }
  799. if (p_property == "empty_animation_duration") {
  800. empty_animation_duration = p_value;
  801. return true;
  802. }
  803. if (p_property == "track_count") {
  804. set_current_animation_count(p_value);
  805. return true;
  806. }
  807. String p = p_property;
  808. if (p.size() > 2 && p[0] == 'c' && p[1] == 'a' && p[2] == '/') {
  809. Vector<String> sp = p.split("/");
  810. if (sp.size() > 2) {
  811. int64_t id = sp[1].to_int64();
  812. if (id >= 0 && id < current_animations.size()) {
  813. auto &key = sp[2];
  814. if (current_animations[id].get_type() != Variant::DICTIONARY) {
  815. current_animations.set(id, Dictionary());
  816. }
  817. Dictionary dic = current_animations.get(id);
  818. dic[key] = p_value;
  819. _validate_and_play_current_animations();
  820. return true;
  821. }
  822. }
  823. }
  824. return false;
  825. }
  826. int64_t SpineSprite::get_current_animation_count() const {
  827. return current_animations.size();
  828. }
  829. void SpineSprite::set_current_animation_count(int64_t v) {
  830. if (v < 0) v = 0;
  831. while (current_animations.size() < v) {
  832. Dictionary d;
  833. d["track_id"] = current_animations.size();
  834. d["animation"] = "";
  835. d["delay"] = 0;
  836. d["loop"] = true;
  837. d["empty"] = false;
  838. d["empty_animation_duration"] = 0.3;
  839. d["clear"] = false;
  840. current_animations.push_back(d);
  841. }
  842. while (current_animations.size() > v) {
  843. if (animation_state.is_valid() && skeleton.is_valid()) {
  844. if (current_animations.back().get_type() == Variant::DICTIONARY) {
  845. Dictionary back = current_animations.back();
  846. if (back.has("track_id")) {
  847. int64_t track_id = back["track_id"];
  848. int track_cnt = 0;
  849. for (size_t i=0; i<current_animations.size(); ++i) {
  850. if (current_animations[i].get_type() == Variant::DICTIONARY) {
  851. Dictionary d = current_animations[i];
  852. if (d.has("track_id") && track_id == (int64_t)d["track_id"]) {
  853. track_cnt += 1;
  854. }
  855. }
  856. }
  857. if (track_cnt == 0)
  858. animation_state->clear_track(track_id);
  859. }
  860. }
  861. }
  862. current_animations.pop_back();
  863. }
  864. property_list_changed_notify();
  865. }
  866. void SpineSprite::_validate_and_play_current_animations() {
  867. if(animation_state.is_valid() && skeleton.is_valid()){
  868. int64_t track_cnt = 0;
  869. HashMap<int64_t, bool> has_track;
  870. for(size_t i=0; i<current_animations.size(); ++i) {
  871. auto a = current_animations[i];
  872. if(a.get_type() == Variant::DICTIONARY){
  873. Dictionary d = a;
  874. int64_t track_id = 0;
  875. String animation = "";
  876. float delay = 0;
  877. bool loop = true;
  878. bool empty = false;
  879. float empty_animation_duration = 0.3;
  880. bool clear = false;
  881. if (d.has("track_id")) track_id = d["track_id"];
  882. if (d.has("animation")) animation = d["animation"];
  883. if (d.has("delay")) delay = d["delay"];
  884. if (d.has("loop")) loop = d["loop"];
  885. if (d.has("empty")) empty = d["empty"];
  886. if (d.has("empty_animation_duration")) empty_animation_duration = d["empty_animation_duration"];
  887. if (d.has("clear")) clear = d["clear"];
  888. if (track_id < 0) {
  889. print_line(vformat("track_id at 'ID %d' can not be less than 0!", (unsigned int)i));
  890. continue;
  891. }
  892. track_cnt += 1;
  893. if (empty) {
  894. if (has_track.has(track_id))
  895. animation_state->add_empty_animation(track_id, empty_animation_duration, delay);
  896. else
  897. animation_state->set_empty_animation(track_id, empty_animation_duration);
  898. has_track[track_id] = true;
  899. } else if (clear) {
  900. animation_state->clear_track(track_id);
  901. } else if (skeleton->get_data()->find_animation(animation).is_valid()) {
  902. if (has_track.has(track_id))
  903. animation_state->add_animation(animation, delay, loop, track_id);
  904. else
  905. animation_state->set_animation(animation, loop, track_id);
  906. has_track[track_id] = true;
  907. }
  908. }
  909. }
  910. if (track_cnt == 0) animation_state->clear_tracks();
  911. }
  912. }