1 /*************************************************************************/
2 /*  bone_attachment.cpp                                                  */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)    */
10 /*                                                                       */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the       */
13 /* "Software"), to deal in the Software without restriction, including   */
14 /* without limitation the rights to use, copy, modify, merge, publish,   */
15 /* distribute, sublicense, and/or sell copies of the Software, and to    */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions:                                             */
18 /*                                                                       */
19 /* The above copyright notice and this permission notice shall be        */
20 /* included in all copies or substantial portions of the Software.       */
21 /*                                                                       */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
29 /*************************************************************************/
30 #include "bone_attachment.h"
31 
_get(const StringName & p_name,Variant & r_ret) const32 bool BoneAttachment::_get(const StringName &p_name, Variant &r_ret) const {
33 
34 	if (String(p_name) == "bone_name") {
35 
36 		r_ret = get_bone_name();
37 		return true;
38 	}
39 
40 	return false;
41 }
_set(const StringName & p_name,const Variant & p_value)42 bool BoneAttachment::_set(const StringName &p_name, const Variant &p_value) {
43 
44 	if (String(p_name) == "bone_name") {
45 
46 		set_bone_name(p_value);
47 		return true;
48 	}
49 
50 	return false;
51 }
_get_property_list(List<PropertyInfo> * p_list) const52 void BoneAttachment::_get_property_list(List<PropertyInfo> *p_list) const {
53 
54 	Skeleton *parent = NULL;
55 	if (get_parent())
56 		parent = get_parent()->cast_to<Skeleton>();
57 
58 	if (parent) {
59 
60 		String names;
61 		for (int i = 0; i < parent->get_bone_count(); i++) {
62 			if (i > 0)
63 				names += ",";
64 			names += parent->get_bone_name(i);
65 		}
66 
67 		p_list->push_back(PropertyInfo(Variant::STRING, "bone_name", PROPERTY_HINT_ENUM, names));
68 	} else {
69 
70 		p_list->push_back(PropertyInfo(Variant::STRING, "bone_name"));
71 	}
72 }
73 
_check_bind()74 void BoneAttachment::_check_bind() {
75 
76 	if (get_parent() && get_parent()->cast_to<Skeleton>()) {
77 		Skeleton *sk = get_parent()->cast_to<Skeleton>();
78 		int idx = sk->find_bone(bone_name);
79 		if (idx != -1) {
80 			sk->bind_child_node_to_bone(idx, this);
81 			set_transform(sk->get_bone_global_pose(idx));
82 			bound = true;
83 		}
84 	}
85 }
86 
_check_unbind()87 void BoneAttachment::_check_unbind() {
88 
89 	if (bound) {
90 
91 		if (get_parent() && get_parent()->cast_to<Skeleton>()) {
92 			Skeleton *sk = get_parent()->cast_to<Skeleton>();
93 			int idx = sk->find_bone(bone_name);
94 			if (idx != -1) {
95 				sk->unbind_child_node_from_bone(idx, this);
96 			}
97 		}
98 		bound = false;
99 	}
100 }
101 
set_bone_name(const String & p_name)102 void BoneAttachment::set_bone_name(const String &p_name) {
103 
104 	if (is_inside_tree())
105 		_check_unbind();
106 
107 	bone_name = p_name;
108 
109 	if (is_inside_tree())
110 		_check_bind();
111 }
112 
get_bone_name() const113 String BoneAttachment::get_bone_name() const {
114 
115 	return bone_name;
116 }
117 
_notification(int p_what)118 void BoneAttachment::_notification(int p_what) {
119 
120 	switch (p_what) {
121 
122 		case NOTIFICATION_ENTER_TREE: {
123 
124 			_check_bind();
125 		} break;
126 		case NOTIFICATION_EXIT_TREE: {
127 
128 			_check_unbind();
129 		} break;
130 	}
131 }
132 
BoneAttachment()133 BoneAttachment::BoneAttachment() {
134 	bound = false;
135 }
136 
_bind_methods()137 void BoneAttachment::_bind_methods() {
138 	ObjectTypeDB::bind_method(_MD("set_bone_name", "bone_name"), &BoneAttachment::set_bone_name);
139 	ObjectTypeDB::bind_method(_MD("get_bone_name"), &BoneAttachment::get_bone_name);
140 }
141