SpineSkeletonDataResource.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825
  1. /******************************************************************************
  2. * Spine Runtimes License Agreement
  3. * Last updated April 5, 2025. Replaces all prior versions.
  4. *
  5. * Copyright (c) 2013-2025, 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 "SpineSkeletonDataResource.h"
  30. #include "SpineCommon.h"
  31. #ifdef SPINE_GODOT_EXTENSION
  32. #include <godot_cpp/classes/encoded_object_as_id.hpp>
  33. #include <godot_cpp/classes/engine.hpp>
  34. #include <godot_cpp/classes/editor_interface.hpp>
  35. #else
  36. #if VERSION_MAJOR > 3
  37. #include "core/config/engine.h"
  38. #include "editor/editor_interface.h"
  39. #else
  40. #include "core/engine.h"
  41. #endif
  42. #include <core/io/marshalls.h>
  43. #endif
  44. #ifdef TOOLS_ENABLED
  45. #ifdef SPINE_GODOT_EXTENSION
  46. #include <godot_cpp/classes/editor_file_system.hpp>
  47. #else
  48. #include "editor/editor_file_system.h"
  49. #endif
  50. #endif
  51. void SpineAnimationMix::_bind_methods() {
  52. ClassDB::bind_method(D_METHOD("set_from", "from"),
  53. &SpineAnimationMix::set_from);
  54. ClassDB::bind_method(D_METHOD("get_from"), &SpineAnimationMix::get_from);
  55. ClassDB::bind_method(D_METHOD("set_to", "to"), &SpineAnimationMix::set_to);
  56. ClassDB::bind_method(D_METHOD("get_to"), &SpineAnimationMix::get_to);
  57. ClassDB::bind_method(D_METHOD("set_mix", "mix"), &SpineAnimationMix::set_mix);
  58. ClassDB::bind_method(D_METHOD("get_mix"), &SpineAnimationMix::get_mix);
  59. ADD_PROPERTY(PropertyInfo(Variant::STRING, "from"), "set_from", "get_from");
  60. ADD_PROPERTY(PropertyInfo(Variant::STRING, "to"), "set_to", "get_to");
  61. #if VERSION_MAJOR > 3
  62. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mix"), "set_mix", "get_mix");
  63. #else
  64. ADD_PROPERTY(PropertyInfo(Variant::REAL, "mix"), "set_mix", "get_mix");
  65. #endif
  66. }
  67. SpineAnimationMix::SpineAnimationMix() : from(""), to(""), mix(0) {}
  68. void SpineAnimationMix::set_from(const String &_from) { this->from = _from; }
  69. String SpineAnimationMix::get_from() { return from; }
  70. void SpineAnimationMix::set_to(const String &_to) { this->to = _to; }
  71. String SpineAnimationMix::get_to() { return to; }
  72. void SpineAnimationMix::set_mix(float _mix) { this->mix = _mix; }
  73. float SpineAnimationMix::get_mix() { return mix; }
  74. void SpineSkeletonDataResource::_bind_methods() {
  75. ClassDB::bind_method(D_METHOD("is_skeleton_data_loaded"),
  76. &SpineSkeletonDataResource::is_skeleton_data_loaded);
  77. ClassDB::bind_method(D_METHOD("set_atlas_res", "atlas_res"),
  78. &SpineSkeletonDataResource::set_atlas_res);
  79. ClassDB::bind_method(D_METHOD("get_atlas_res"),
  80. &SpineSkeletonDataResource::get_atlas_res);
  81. ClassDB::bind_method(D_METHOD("set_skeleton_file_res", "skeleton_file_res"),
  82. &SpineSkeletonDataResource::set_skeleton_file_res);
  83. ClassDB::bind_method(D_METHOD("get_skeleton_file_res"),
  84. &SpineSkeletonDataResource::get_skeleton_file_res);
  85. ClassDB::bind_method(D_METHOD("set_default_mix", "default_mix"),
  86. &SpineSkeletonDataResource::set_default_mix);
  87. ClassDB::bind_method(D_METHOD("get_default_mix"),
  88. &SpineSkeletonDataResource::get_default_mix);
  89. ClassDB::bind_method(D_METHOD("set_animation_mixes", "mixes"),
  90. &SpineSkeletonDataResource::set_animation_mixes);
  91. ClassDB::bind_method(D_METHOD("get_animation_mixes"),
  92. &SpineSkeletonDataResource::get_animation_mixes);
  93. // Spine API
  94. ClassDB::bind_method(D_METHOD("find_bone", "bone_name"),
  95. &SpineSkeletonDataResource::find_bone);
  96. ClassDB::bind_method(D_METHOD("find_slot", "slot_name"),
  97. &SpineSkeletonDataResource::find_slot);
  98. ClassDB::bind_method(D_METHOD("find_skin", "skin_name"),
  99. &SpineSkeletonDataResource::find_skin);
  100. ClassDB::bind_method(D_METHOD("find_event", "event_data_name"),
  101. &SpineSkeletonDataResource::find_event);
  102. ClassDB::bind_method(D_METHOD("find_animation", "animation_name"),
  103. &SpineSkeletonDataResource::find_animation);
  104. ClassDB::bind_method(D_METHOD("find_ik_constraint_data", "constraint_name"),
  105. &SpineSkeletonDataResource::find_ik_constraint);
  106. ClassDB::bind_method(
  107. D_METHOD("find_transform_constraint_data", "constraint_name"),
  108. &SpineSkeletonDataResource::find_transform_constraint);
  109. ClassDB::bind_method(D_METHOD("find_path_constraint_data", "constraint_name"),
  110. &SpineSkeletonDataResource::find_path_constraint);
  111. ClassDB::bind_method(D_METHOD("find_physics_constraint_data", "constraint_name"),
  112. &SpineSkeletonDataResource::find_physics_constraint);
  113. ClassDB::bind_method(D_METHOD("get_skeleton_name"),
  114. &SpineSkeletonDataResource::get_skeleton_name);
  115. ClassDB::bind_method(D_METHOD("get_bones"),
  116. &SpineSkeletonDataResource::get_bones);
  117. ClassDB::bind_method(D_METHOD("get_slots"),
  118. &SpineSkeletonDataResource::get_slots);
  119. ClassDB::bind_method(D_METHOD("get_skins"),
  120. &SpineSkeletonDataResource::get_skins);
  121. ClassDB::bind_method(D_METHOD("get_default_skin"),
  122. &SpineSkeletonDataResource::get_default_skin);
  123. ClassDB::bind_method(D_METHOD("set_default_skin", "skin"),
  124. &SpineSkeletonDataResource::set_default_skin);
  125. ClassDB::bind_method(D_METHOD("get_events"),
  126. &SpineSkeletonDataResource::get_events);
  127. ClassDB::bind_method(D_METHOD("get_animations"),
  128. &SpineSkeletonDataResource::get_animations);
  129. ClassDB::bind_method(D_METHOD("get_ik_constraints"),
  130. &SpineSkeletonDataResource::get_ik_constraints);
  131. ClassDB::bind_method(D_METHOD("get_transform_constraints"),
  132. &SpineSkeletonDataResource::get_transform_constraints);
  133. ClassDB::bind_method(D_METHOD("get_path_constraints"),
  134. &SpineSkeletonDataResource::get_path_constraints);
  135. ClassDB::bind_method(D_METHOD("get_physics_constraints"),
  136. &SpineSkeletonDataResource::get_physics_constraints);
  137. ClassDB::bind_method(D_METHOD("get_x"), &SpineSkeletonDataResource::get_x);
  138. ClassDB::bind_method(D_METHOD("get_y"), &SpineSkeletonDataResource::get_y);
  139. ClassDB::bind_method(D_METHOD("get_width"),
  140. &SpineSkeletonDataResource::get_width);
  141. ClassDB::bind_method(D_METHOD("get_height"),
  142. &SpineSkeletonDataResource::get_height);
  143. ClassDB::bind_method(D_METHOD("get_version"),
  144. &SpineSkeletonDataResource::get_version);
  145. ClassDB::bind_method(D_METHOD("get_hash"),
  146. &SpineSkeletonDataResource::get_hash);
  147. ClassDB::bind_method(D_METHOD("get_images_path"),
  148. &SpineSkeletonDataResource::get_images_path);
  149. ClassDB::bind_method(D_METHOD("get_audio_path"),
  150. &SpineSkeletonDataResource::get_audio_path);
  151. ClassDB::bind_method(D_METHOD("get_fps"),
  152. &SpineSkeletonDataResource::get_fps);
  153. ClassDB::bind_method(D_METHOD("get_reference_scale"),
  154. &SpineSkeletonDataResource::get_reference_scale);
  155. ClassDB::bind_method(D_METHOD("set_reference_scale", "reference_scale"),
  156. &SpineSkeletonDataResource::set_reference_scale);
  157. ClassDB::bind_method(D_METHOD("update_skeleton_data"),
  158. &SpineSkeletonDataResource::update_skeleton_data);
  159. ADD_SIGNAL(MethodInfo("skeleton_data_changed"));
  160. ADD_SIGNAL(MethodInfo("_internal_spine_objects_invalidated"));
  161. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "atlas_res",
  162. PropertyHint::PROPERTY_HINT_RESOURCE_TYPE,
  163. "SpineAtlasResource"),
  164. "set_atlas_res", "get_atlas_res");
  165. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "skeleton_file_res",
  166. PropertyHint::PROPERTY_HINT_RESOURCE_TYPE,
  167. "SpineSkeletonFileResource"),
  168. "set_skeleton_file_res", "get_skeleton_file_res");
  169. #if VERSION_MAJOR > 3
  170. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "default_mix"), "set_default_mix",
  171. "get_default_mix");
  172. #else
  173. ADD_PROPERTY(PropertyInfo(Variant::REAL, "default_mix"), "set_default_mix",
  174. "get_default_mix");
  175. #endif
  176. ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "animation_mixes"),
  177. "set_animation_mixes", "get_animation_mixes");
  178. #ifdef TOOLS_ENABLED
  179. #if VERSION_MAJOR > 3
  180. ClassDB::bind_method(D_METHOD("_on_resources_reimported", "resources"),
  181. &SpineSkeletonDataResource::_on_resources_reimported);
  182. #else
  183. ClassDB::bind_method(D_METHOD("_on_resources_reimported", "resources"),
  184. &SpineSkeletonDataResource::_on_resources_reimported);
  185. #endif
  186. #endif
  187. }
  188. #ifdef TOOLS_ENABLED
  189. EditorFileSystem *get_editor_file_system() {
  190. #ifdef SPINE_GODOT_EXTENSION
  191. EditorInterface *editor_interface = EditorInterface::get_singleton();
  192. if (editor_interface) {
  193. return editor_interface->get_resource_filesystem();
  194. }
  195. return nullptr;
  196. #else
  197. return EditorFileSystem::get_singleton();
  198. #endif
  199. }
  200. #endif
  201. SpineSkeletonDataResource::SpineSkeletonDataResource()
  202. : default_mix(0), skeleton_data(nullptr), animation_state_data(nullptr) {
  203. #ifdef TOOLS_ENABLED
  204. #if VERSION_MAJOR > 3
  205. if (Engine::get_singleton()->is_editor_hint()) {
  206. EditorFileSystem *efs = get_editor_file_system();
  207. if (efs) {
  208. efs->connect("resources_reimported", callable_mp(this, &SpineSkeletonDataResource::_on_resources_reimported));
  209. }
  210. }
  211. #else
  212. if (Engine::get_singleton()->is_editor_hint()) {
  213. EditorFileSystem *efs = EditorFileSystem::get_singleton();
  214. if (efs) {
  215. efs->connect("resources_reimported", this, "_on_resources_reimported");
  216. }
  217. }
  218. #endif
  219. #endif
  220. }
  221. SpineSkeletonDataResource::~SpineSkeletonDataResource() {
  222. #ifdef TOOLS_ENABLED
  223. #if VERSION_MAJOR > 3
  224. if (Engine::get_singleton()->is_editor_hint()) {
  225. EditorFileSystem *efs = get_editor_file_system();
  226. if (efs && efs->is_connected("resources_reimported", callable_mp(this, &SpineSkeletonDataResource::_on_resources_reimported))) {
  227. efs->disconnect("resources_reimported", callable_mp(this, &SpineSkeletonDataResource::_on_resources_reimported));
  228. }
  229. }
  230. #else
  231. if (Engine::get_singleton()->is_editor_hint()) {
  232. EditorFileSystem *efs = EditorFileSystem::get_singleton();
  233. if (efs && efs->is_connected("resources_reimported", this, "_on_resources_reimported")) {
  234. efs->disconnect("resources_reimported", this, "_on_resources_reimported");
  235. }
  236. }
  237. #endif
  238. #endif
  239. delete skeleton_data;
  240. delete animation_state_data;
  241. }
  242. #ifdef TOOLS_ENABLED
  243. #if VERSION_MAJOR > 3
  244. void SpineSkeletonDataResource::_on_resources_reimported(const PackedStringArray &resources) {
  245. for (int i = 0; i < resources.size(); i++) {
  246. if (atlas_res.is_valid() && atlas_res->get_path() == resources[i]) {
  247. #ifdef SPINE_GODOT_EXTENSION
  248. atlas_res = ResourceLoader::get_singleton()->load(resources[i], "SpineAtlasResource", ResourceLoader::CACHE_MODE_IGNORE);
  249. #else
  250. atlas_res = ResourceLoader::load(resources[i], "SpineAtlasResource", ResourceFormatLoader::CACHE_MODE_IGNORE);
  251. #endif
  252. update_skeleton_data();
  253. } else if (skeleton_file_res.is_valid() && skeleton_file_res->get_path() == resources[i]) {
  254. #ifdef SPINE_GODOT_EXTENSION
  255. skeleton_file_res = ResourceLoader::get_singleton()->load(resources[i], "SpineSkeletonFileResource", ResourceLoader::CACHE_MODE_IGNORE);
  256. #else
  257. skeleton_file_res = ResourceLoader::load(resources[i], "SpineSkeletonFileResource", ResourceFormatLoader::CACHE_MODE_IGNORE);
  258. #endif
  259. update_skeleton_data();
  260. }
  261. }
  262. }
  263. #else
  264. void SpineSkeletonDataResource::_on_resources_reimported(const PoolStringArray &resources) {
  265. for (int i = 0; i < resources.size(); i++) {
  266. if (atlas_res.is_valid() && atlas_res->get_path() == resources[i]) {
  267. atlas_res = ResourceLoader::load(resources[i]);
  268. update_skeleton_data();
  269. } else if (skeleton_file_res.is_valid() && skeleton_file_res->get_path() == resources[i]) {
  270. skeleton_file_res = ResourceLoader::load(resources[i]);
  271. update_skeleton_data();
  272. }
  273. }
  274. }
  275. #endif
  276. #endif
  277. void SpineSkeletonDataResource::update_skeleton_data() {
  278. if (skeleton_data) {
  279. delete skeleton_data;
  280. skeleton_data = nullptr;
  281. }
  282. if (animation_state_data) {
  283. delete animation_state_data;
  284. animation_state_data = nullptr;
  285. }
  286. emit_signal(SNAME("_internal_spine_objects_invalidated"));
  287. if (atlas_res.is_valid() && skeleton_file_res.is_valid()) {
  288. load_resources(atlas_res->get_spine_atlas(), skeleton_file_res->get_json(),
  289. skeleton_file_res->get_binary());
  290. }
  291. emit_signal(SNAME("skeleton_data_changed"));
  292. #ifdef TOOLS_ENABLED
  293. NOTIFY_PROPERTY_LIST_CHANGED();
  294. #endif
  295. }
  296. #ifdef SPINE_GODOT_EXTENSION
  297. void SpineSkeletonDataResource::load_resources(spine::Atlas *atlas,
  298. const String &json,
  299. const PackedByteArray &binary) {
  300. #else
  301. void SpineSkeletonDataResource::load_resources(spine::Atlas *atlas,
  302. const String &json,
  303. const Vector<uint8_t> &binary) {
  304. #endif
  305. if ((EMPTY(json) && EMPTY(binary)) || atlas == nullptr)
  306. return;
  307. spine::SkeletonData *data;
  308. if (!EMPTY(json)) {
  309. spine::SkeletonJson skeletonJson(atlas);
  310. data = skeletonJson.readSkeletonData(json.utf8());
  311. if (!data) {
  312. ERR_PRINT(String("Error while loading skeleton data: ") + get_path());
  313. ERR_PRINT(String("Error message: ") + skeletonJson.getError().buffer());
  314. return;
  315. }
  316. } else {
  317. spine::SkeletonBinary skeletonBinary(atlas);
  318. data = skeletonBinary.readSkeletonData(binary.ptr(), binary.size());
  319. if (!data) {
  320. ERR_PRINT(String("Error while loading skeleton data: ") + get_path());
  321. ERR_PRINT(String("Error message: ") + skeletonBinary.getError().buffer());
  322. return;
  323. }
  324. }
  325. skeleton_data = data;
  326. animation_state_data = new spine::AnimationStateData(data);
  327. update_mixes();
  328. }
  329. bool SpineSkeletonDataResource::is_skeleton_data_loaded() const {
  330. return skeleton_data != nullptr;
  331. }
  332. void SpineSkeletonDataResource::set_atlas_res(
  333. const Ref<SpineAtlasResource> &atlas) {
  334. atlas_res = atlas;
  335. update_skeleton_data();
  336. }
  337. Ref<SpineAtlasResource> SpineSkeletonDataResource::get_atlas_res() {
  338. return atlas_res;
  339. }
  340. void SpineSkeletonDataResource::set_skeleton_file_res(
  341. const Ref<SpineSkeletonFileResource> &skeleton_file) {
  342. skeleton_file_res = skeleton_file;
  343. update_skeleton_data();
  344. }
  345. Ref<SpineSkeletonFileResource>
  346. SpineSkeletonDataResource::get_skeleton_file_res() {
  347. return skeleton_file_res;
  348. }
  349. #ifdef SPINE_GODOT_EXTENSION
  350. void SpineSkeletonDataResource::get_animation_names(PackedStringArray &animation_names) const {
  351. #else
  352. void SpineSkeletonDataResource::get_animation_names(Vector<String> &animation_names) const {
  353. #endif
  354. animation_names.clear();
  355. if (!is_skeleton_data_loaded())
  356. return;
  357. auto animations = skeleton_data->getAnimations();
  358. for (size_t i = 0; i < animations.size(); ++i) {
  359. auto animation = animations[i];
  360. String name;
  361. name.parse_utf8(animation->getName().buffer());
  362. animation_names.push_back(name);
  363. }
  364. }
  365. #ifdef SPINE_GODOT_EXTENSION
  366. void SpineSkeletonDataResource::get_skin_names(PackedStringArray &skin_names) const {
  367. #else
  368. void SpineSkeletonDataResource::get_skin_names(Vector<String> &skin_names) const {
  369. #endif
  370. skin_names.clear();
  371. if (!is_skeleton_data_loaded())
  372. return;
  373. auto skins = skeleton_data->getSkins();
  374. for (size_t i = 0; i < skins.size(); ++i) {
  375. auto skin = skins[i];
  376. String name;
  377. name.parse_utf8(skin->getName().buffer());
  378. skin_names.push_back(name);
  379. }
  380. }
  381. #ifdef SPINE_GODOT_EXTENSION
  382. void SpineSkeletonDataResource::get_slot_names(PackedStringArray &slot_names) {
  383. #else
  384. void SpineSkeletonDataResource::get_slot_names(Vector<String> &slot_names) {
  385. #endif
  386. slot_names.clear();
  387. if (!is_skeleton_data_loaded())
  388. return;
  389. auto slots = skeleton_data->getSlots();
  390. for (size_t i = 0; i < slots.size(); ++i) {
  391. auto slot = slots[i];
  392. String name;
  393. name.parse_utf8(slot->getName().buffer());
  394. slot_names.push_back(name);
  395. }
  396. }
  397. #ifdef SPINE_GODOT_EXTENSION
  398. void SpineSkeletonDataResource::get_bone_names(PackedStringArray &bone_names) {
  399. #else
  400. void SpineSkeletonDataResource::get_bone_names(Vector<String> &bone_names) {
  401. #endif
  402. bone_names.clear();
  403. if (!is_skeleton_data_loaded())
  404. return;
  405. auto bones = skeleton_data->getBones();
  406. for (size_t i = 0; i < bones.size(); ++i) {
  407. auto bone = bones[i];
  408. String name;
  409. name.parse_utf8(bone->getName().buffer());
  410. bone_names.push_back(name);
  411. }
  412. }
  413. void SpineSkeletonDataResource::set_default_mix(float _default_mix) {
  414. this->default_mix = _default_mix;
  415. update_mixes();
  416. }
  417. float SpineSkeletonDataResource::get_default_mix() { return default_mix; }
  418. void SpineSkeletonDataResource::set_animation_mixes(Array _animation_mixes) {
  419. for (int i = 0; i < _animation_mixes.size(); i++) {
  420. auto objectId = Object::cast_to<EncodedObjectAsID>(_animation_mixes[0]);
  421. if (objectId) {
  422. ERR_PRINT("Live-editing of animation mixes is not supported.");
  423. return;
  424. }
  425. }
  426. this->animation_mixes = _animation_mixes;
  427. update_mixes();
  428. }
  429. Array SpineSkeletonDataResource::get_animation_mixes() {
  430. return animation_mixes;
  431. }
  432. void SpineSkeletonDataResource::update_mixes() {
  433. if (!is_skeleton_data_loaded())
  434. return;
  435. animation_state_data->clear();
  436. animation_state_data->setDefaultMix(default_mix);
  437. for (int i = 0; i < animation_mixes.size(); i++) {
  438. Ref<SpineAnimationMix> mix = animation_mixes[i];
  439. spine::Animation *from =
  440. skeleton_data->findAnimation(mix->get_from().utf8().ptr());
  441. spine::Animation *to =
  442. skeleton_data->findAnimation(mix->get_to().utf8().ptr());
  443. if (!from) {
  444. ERR_PRINT(vformat("Failed to set animation mix %s->%s. Animation %s does "
  445. "not exist in skeleton.",
  446. from, to, from));
  447. continue;
  448. }
  449. if (!to) {
  450. ERR_PRINT(vformat("Failed to set animation mix %s->%s. Animation %s does "
  451. "not exist in skeleton.",
  452. from, to, to));
  453. continue;
  454. }
  455. animation_state_data->setMix(from, to, mix->get_mix());
  456. }
  457. }
  458. Ref<SpineAnimation>
  459. SpineSkeletonDataResource::find_animation(const String &animation_name) const {
  460. SPINE_CHECK(skeleton_data, nullptr)
  461. if (EMPTY(animation_name))
  462. return nullptr;
  463. auto animation =
  464. skeleton_data->findAnimation(SPINE_STRING_TMP(animation_name));
  465. if (!animation)
  466. return nullptr;
  467. Ref<SpineAnimation> animation_ref(memnew(SpineAnimation));
  468. animation_ref->set_spine_object(this, animation);
  469. return animation_ref;
  470. }
  471. Ref<SpineBoneData>
  472. SpineSkeletonDataResource::find_bone(const String &bone_name) const {
  473. SPINE_CHECK(skeleton_data, nullptr)
  474. if (EMPTY(bone_name))
  475. return nullptr;
  476. auto bone = skeleton_data->findBone(SPINE_STRING_TMP(bone_name));
  477. if (!bone)
  478. return nullptr;
  479. Ref<SpineBoneData> bone_ref(memnew(SpineBoneData));
  480. bone_ref->set_spine_object(this, bone);
  481. return bone_ref;
  482. }
  483. Ref<SpineSlotData>
  484. SpineSkeletonDataResource::find_slot(const String &slot_name) const {
  485. SPINE_CHECK(skeleton_data, nullptr)
  486. if (EMPTY(slot_name))
  487. return nullptr;
  488. auto slot = skeleton_data->findSlot(SPINE_STRING_TMP(slot_name));
  489. if (!slot)
  490. return nullptr;
  491. Ref<SpineSlotData> slot_ref(memnew(SpineSlotData));
  492. slot_ref->set_spine_object(this, slot);
  493. return slot_ref;
  494. }
  495. Ref<SpineSkin>
  496. SpineSkeletonDataResource::find_skin(const String &skin_name) const {
  497. SPINE_CHECK(skeleton_data, nullptr)
  498. if (EMPTY(skin_name))
  499. return nullptr;
  500. auto skin = skeleton_data->findSkin(SPINE_STRING_TMP(skin_name));
  501. if (!skin)
  502. return nullptr;
  503. Ref<SpineSkin> skin_ref(memnew(SpineSkin));
  504. skin_ref->set_spine_object(this, skin);
  505. return skin_ref;
  506. }
  507. Ref<SpineEventData>
  508. SpineSkeletonDataResource::find_event(const String &event_data_name) const {
  509. SPINE_CHECK(skeleton_data, nullptr)
  510. if (EMPTY(event_data_name))
  511. return nullptr;
  512. auto event = skeleton_data->findEvent(SPINE_STRING_TMP(event_data_name));
  513. if (!event)
  514. return nullptr;
  515. Ref<SpineEventData> event_ref(memnew(SpineEventData));
  516. event_ref->set_spine_object(this, event);
  517. return event_ref;
  518. }
  519. Ref<SpineIkConstraintData> SpineSkeletonDataResource::find_ik_constraint(
  520. const String &constraint_name) const {
  521. SPINE_CHECK(skeleton_data, nullptr)
  522. if (EMPTY(constraint_name))
  523. return nullptr;
  524. auto constraint =
  525. skeleton_data->findIkConstraint(SPINE_STRING_TMP(constraint_name));
  526. if (!constraint)
  527. return nullptr;
  528. Ref<SpineIkConstraintData> constraint_ref(memnew(SpineIkConstraintData));
  529. constraint_ref->set_spine_object(this, constraint);
  530. return constraint_ref;
  531. }
  532. Ref<SpineTransformConstraintData>
  533. SpineSkeletonDataResource::find_transform_constraint(
  534. const String &constraint_name) const {
  535. SPINE_CHECK(skeleton_data, nullptr)
  536. if (EMPTY(constraint_name))
  537. return nullptr;
  538. auto constraint =
  539. skeleton_data->findTransformConstraint(SPINE_STRING_TMP(constraint_name));
  540. if (!constraint)
  541. return nullptr;
  542. Ref<SpineTransformConstraintData> constraint_ref(
  543. memnew(SpineTransformConstraintData));
  544. constraint_ref->set_spine_object(this, constraint);
  545. return constraint_ref;
  546. }
  547. Ref<SpinePathConstraintData> SpineSkeletonDataResource::find_path_constraint(
  548. const String &constraint_name) const {
  549. SPINE_CHECK(skeleton_data, nullptr)
  550. if (EMPTY(constraint_name))
  551. return nullptr;
  552. auto constraint =
  553. skeleton_data->findPathConstraint(SPINE_STRING_TMP(constraint_name));
  554. if (constraint == nullptr)
  555. return nullptr;
  556. Ref<SpinePathConstraintData> constraint_ref(memnew(SpinePathConstraintData));
  557. constraint_ref->set_spine_object(this, constraint);
  558. return constraint_ref;
  559. }
  560. Ref<SpinePhysicsConstraintData>
  561. SpineSkeletonDataResource::find_physics_constraint(
  562. const String &constraint_name) const {
  563. SPINE_CHECK(skeleton_data, nullptr)
  564. if (EMPTY(constraint_name))
  565. return nullptr;
  566. auto constraint =
  567. skeleton_data->findPhysicsConstraint(SPINE_STRING_TMP(constraint_name));
  568. if (constraint == nullptr)
  569. return nullptr;
  570. Ref<SpinePhysicsConstraintData> constraint_ref(
  571. memnew(SpinePhysicsConstraintData));
  572. constraint_ref->set_spine_object(this, constraint);
  573. return constraint_ref;
  574. }
  575. String SpineSkeletonDataResource::get_skeleton_name() const {
  576. SPINE_CHECK(skeleton_data, "")
  577. String name;
  578. name.parse_utf8(skeleton_data->getName().buffer());
  579. return name;
  580. }
  581. Array SpineSkeletonDataResource::get_bones() const {
  582. Array result;
  583. SPINE_CHECK(skeleton_data, result)
  584. auto bones = skeleton_data->getBones();
  585. result.resize((int) bones.size());
  586. for (int i = 0; i < bones.size(); ++i) {
  587. Ref<SpineBoneData> bone_ref(memnew(SpineBoneData));
  588. bone_ref->set_spine_object(this, bones[i]);
  589. result[i] = bone_ref;
  590. }
  591. return result;
  592. }
  593. Array SpineSkeletonDataResource::get_slots() const {
  594. Array result;
  595. SPINE_CHECK(skeleton_data, result)
  596. auto slots = skeleton_data->getSlots();
  597. result.resize((int) slots.size());
  598. for (int i = 0; i < slots.size(); ++i) {
  599. Ref<SpineSlotData> slot_ref(memnew(SpineSlotData));
  600. slot_ref->set_spine_object(this, slots[i]);
  601. result[i] = slot_ref;
  602. }
  603. return result;
  604. }
  605. Array SpineSkeletonDataResource::get_skins() const {
  606. Array result;
  607. SPINE_CHECK(skeleton_data, result)
  608. auto skins = skeleton_data->getSkins();
  609. result.resize((int) skins.size());
  610. for (int i = 0; i < skins.size(); ++i) {
  611. Ref<SpineSkin> skin_ref(memnew(SpineSkin));
  612. skin_ref->set_spine_object(this, skins[i]);
  613. result[i] = skin_ref;
  614. }
  615. return result;
  616. }
  617. Ref<SpineSkin> SpineSkeletonDataResource::get_default_skin() const {
  618. SPINE_CHECK(skeleton_data, nullptr)
  619. auto skin = skeleton_data->getDefaultSkin();
  620. if (skin)
  621. return nullptr;
  622. Ref<SpineSkin> skin_ref(memnew(SpineSkin));
  623. skin_ref->set_spine_object(this, skin);
  624. return skin_ref;
  625. }
  626. void SpineSkeletonDataResource::set_default_skin(Ref<SpineSkin> skin) {
  627. SPINE_CHECK(skeleton_data, )
  628. skeleton_data->setDefaultSkin(skin.is_valid() && skin->get_spine_object()
  629. ? skin->get_spine_object()
  630. : nullptr);
  631. }
  632. Array SpineSkeletonDataResource::get_events() const {
  633. Array result;
  634. SPINE_CHECK(skeleton_data, result)
  635. auto events = skeleton_data->getEvents();
  636. result.resize((int) events.size());
  637. for (int i = 0; i < events.size(); ++i) {
  638. Ref<SpineEventData> event_ref(memnew(SpineEventData));
  639. event_ref->set_spine_object(this, events[i]);
  640. result[i] = event_ref;
  641. }
  642. return result;
  643. }
  644. Array SpineSkeletonDataResource::get_animations() const {
  645. Array result;
  646. SPINE_CHECK(skeleton_data, result)
  647. auto animations = skeleton_data->getAnimations();
  648. result.resize((int) animations.size());
  649. for (int i = 0; i < animations.size(); ++i) {
  650. Ref<SpineAnimation> animation_ref(memnew(SpineAnimation));
  651. animation_ref->set_spine_object(this, animations[i]);
  652. result[i] = animation_ref;
  653. }
  654. return result;
  655. }
  656. Array SpineSkeletonDataResource::get_ik_constraints() const {
  657. Array result;
  658. SPINE_CHECK(skeleton_data, result)
  659. auto constraints = skeleton_data->getIkConstraints();
  660. result.resize((int) constraints.size());
  661. for (int i = 0; i < constraints.size(); ++i) {
  662. Ref<SpineIkConstraintData> constraint_ref(memnew(SpineIkConstraintData));
  663. constraint_ref->set_spine_object(this, constraints[i]);
  664. result[i] = constraint_ref;
  665. }
  666. return result;
  667. }
  668. Array SpineSkeletonDataResource::get_transform_constraints() const {
  669. Array result;
  670. SPINE_CHECK(skeleton_data, result)
  671. auto constraints = skeleton_data->getTransformConstraints();
  672. result.resize((int) constraints.size());
  673. for (int i = 0; i < constraints.size(); ++i) {
  674. Ref<SpineTransformConstraintData> constraint_ref(
  675. memnew(SpineTransformConstraintData));
  676. constraint_ref->set_spine_object(this, constraints[i]);
  677. result[i] = constraint_ref;
  678. }
  679. return result;
  680. }
  681. Array SpineSkeletonDataResource::get_path_constraints() const {
  682. Array result;
  683. SPINE_CHECK(skeleton_data, result)
  684. auto constraints = skeleton_data->getPathConstraints();
  685. result.resize((int) constraints.size());
  686. for (int i = 0; i < constraints.size(); ++i) {
  687. Ref<SpinePathConstraintData> constraint_ref(
  688. memnew(SpinePathConstraintData));
  689. constraint_ref->set_spine_object(this, constraints[i]);
  690. result[i] = constraint_ref;
  691. }
  692. return result;
  693. }
  694. Array SpineSkeletonDataResource::get_physics_constraints() const {
  695. Array result;
  696. SPINE_CHECK(skeleton_data, result)
  697. auto constraints = skeleton_data->getPhysicsConstraints();
  698. result.resize((int) constraints.size());
  699. for (int i = 0; i < constraints.size(); ++i) {
  700. Ref<SpinePhysicsConstraintData> constraint_ref(
  701. memnew(SpinePhysicsConstraintData));
  702. constraint_ref->set_spine_object(this, constraints[i]);
  703. result[i] = constraint_ref;
  704. }
  705. return result;
  706. }
  707. float SpineSkeletonDataResource::get_x() const {
  708. SPINE_CHECK(skeleton_data, 0)
  709. return skeleton_data->getX();
  710. }
  711. float SpineSkeletonDataResource::get_y() const {
  712. SPINE_CHECK(skeleton_data, 0)
  713. return skeleton_data->getY();
  714. }
  715. float SpineSkeletonDataResource::get_width() const {
  716. SPINE_CHECK(skeleton_data, 0)
  717. return skeleton_data->getWidth();
  718. }
  719. float SpineSkeletonDataResource::get_height() const {
  720. SPINE_CHECK(skeleton_data, 0)
  721. return skeleton_data->getHeight();
  722. }
  723. String SpineSkeletonDataResource::get_version() const {
  724. SPINE_CHECK(skeleton_data, "")
  725. return skeleton_data->getVersion().buffer();
  726. }
  727. String SpineSkeletonDataResource::get_hash() const {
  728. SPINE_CHECK(skeleton_data, "")
  729. return skeleton_data->getHash().buffer();
  730. }
  731. String SpineSkeletonDataResource::get_images_path() const {
  732. SPINE_CHECK(skeleton_data, "")
  733. return skeleton_data->getImagesPath().buffer();
  734. }
  735. String SpineSkeletonDataResource::get_audio_path() const {
  736. SPINE_CHECK(skeleton_data, "")
  737. return skeleton_data->getAudioPath().buffer();
  738. }
  739. float SpineSkeletonDataResource::get_fps() const {
  740. SPINE_CHECK(skeleton_data, 0)
  741. return skeleton_data->getFps();
  742. }
  743. float SpineSkeletonDataResource::get_reference_scale() const {
  744. SPINE_CHECK(skeleton_data, 100);
  745. return skeleton_data->getReferenceScale();
  746. }
  747. void SpineSkeletonDataResource::set_reference_scale(float reference_scale) {
  748. SPINE_CHECK(skeleton_data, )
  749. skeleton_data->setReferenceScale(reference_scale);
  750. }