| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*  skeleton.cpp                                                         */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							| 
									
										
										
										
											2017-08-27 14:16:55 +02:00
										 |  |  | /*                      https://godotengine.org                          */ | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2017-01-01 22:01:57 +01:00
										 |  |  | /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							| 
									
										
										
										
											2017-04-08 00:11:42 +02:00
										 |  |  | /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */ | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the       */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including   */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,   */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to    */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to */ | 
					
						
							|  |  |  | /* the following conditions:                                             */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be        */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.       */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | #include "skeleton.h"
 | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | #include "message_queue.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-19 17:00:46 -03:00
										 |  |  | #include "core/project_settings.h"
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | #include "scene/resources/surface_tool.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | bool Skeleton::_set(const StringName &p_path, const Variant &p_value) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	String path = p_path; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!path.begins_with("bones/")) | 
					
						
							|  |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	int which = path.get_slicec('/', 1).to_int(); | 
					
						
							|  |  |  | 	String what = path.get_slicec('/', 2); | 
					
						
							| 
									
										
										
										
											2014-02-23 10:35:05 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	if (which == bones.size() && what == "name") { | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		add_bone(p_value); | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX_V(which, bones.size(), false); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	if (what == "parent") | 
					
						
							|  |  |  | 		set_bone_parent(which, p_value); | 
					
						
							|  |  |  | 	else if (what == "rest") | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		set_bone_rest(which, p_value); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	else if (what == "enabled") | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		set_bone_enabled(which, p_value); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	else if (what == "pose") | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		set_bone_pose(which, p_value); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	else if (what == "bound_childs") { | 
					
						
							|  |  |  | 		Array children = p_value; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-29 18:38:32 -03:00
										 |  |  | 		if (is_inside_tree()) { | 
					
						
							|  |  |  | 			bones[which].nodes_bound.clear(); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			for (int i = 0; i < children.size(); i++) { | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				NodePath path = children[i]; | 
					
						
							|  |  |  | 				ERR_CONTINUE(path.operator String() == ""); | 
					
						
							| 
									
										
										
										
											2016-06-29 18:38:32 -03:00
										 |  |  | 				Node *node = get_node(path); | 
					
						
							|  |  |  | 				ERR_CONTINUE(!node); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				bind_child_node_to_bone(which, node); | 
					
						
							| 
									
										
										
										
											2016-06-29 18:38:32 -03:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | bool Skeleton::_get(const StringName &p_path, Variant &r_ret) const { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 	String path = p_path; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!path.begins_with("bones/")) | 
					
						
							|  |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	int which = path.get_slicec('/', 1).to_int(); | 
					
						
							|  |  |  | 	String what = path.get_slicec('/', 2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX_V(which, bones.size(), false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (what == "name") | 
					
						
							|  |  |  | 		r_ret = get_bone_name(which); | 
					
						
							|  |  |  | 	else if (what == "parent") | 
					
						
							|  |  |  | 		r_ret = get_bone_parent(which); | 
					
						
							|  |  |  | 	else if (what == "rest") | 
					
						
							|  |  |  | 		r_ret = get_bone_rest(which); | 
					
						
							|  |  |  | 	else if (what == "enabled") | 
					
						
							|  |  |  | 		r_ret = is_bone_enabled(which); | 
					
						
							|  |  |  | 	else if (what == "pose") | 
					
						
							|  |  |  | 		r_ret = get_bone_pose(which); | 
					
						
							|  |  |  | 	else if (what == "bound_childs") { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		Array children; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		for (const List<uint32_t>::Element *E = bones[which].nodes_bound.front(); E; E = E->next()) { | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			Object *obj = ObjectDB::get_instance(E->get()); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			ERR_CONTINUE(!obj); | 
					
						
							| 
									
										
										
										
											2017-08-24 22:58:51 +02:00
										 |  |  | 			Node *node = Object::cast_to<Node>(obj); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			ERR_CONTINUE(!node); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			NodePath path = get_path_to(node); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			children.push_back(path); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		r_ret = children; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} else | 
					
						
							|  |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void Skeleton::_get_property_list(List<PropertyInfo> *p_list) const { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < bones.size(); i++) { | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		String prep = "bones/" + itos(i) + "/"; | 
					
						
							|  |  |  | 		p_list->push_back(PropertyInfo(Variant::STRING, prep + "name")); | 
					
						
							|  |  |  | 		p_list->push_back(PropertyInfo(Variant::INT, prep + "parent", PROPERTY_HINT_RANGE, "-1," + itos(i - 1) + ",1")); | 
					
						
							|  |  |  | 		p_list->push_back(PropertyInfo(Variant::TRANSFORM, prep + "rest")); | 
					
						
							|  |  |  | 		p_list->push_back(PropertyInfo(Variant::BOOL, prep + "enabled")); | 
					
						
							|  |  |  | 		p_list->push_back(PropertyInfo(Variant::TRANSFORM, prep + "pose", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); | 
					
						
							|  |  |  | 		p_list->push_back(PropertyInfo(Variant::ARRAY, prep + "bound_childs")); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Skeleton::_notification(int p_what) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	switch (p_what) { | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		case NOTIFICATION_ENTER_WORLD: { | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			if (dirty) { | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				dirty = false; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				_make_dirty(); // property make it dirty
 | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		} break; | 
					
						
							|  |  |  | 		case NOTIFICATION_EXIT_WORLD: { | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-29 10:54:01 -03:00
										 |  |  | 		} break; | 
					
						
							|  |  |  | 		case NOTIFICATION_TRANSFORM_CHANGED: { | 
					
						
							| 
									
										
										
										
											2017-12-29 11:34:36 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			//if moved, just update transforms
 | 
					
						
							|  |  |  | 			VisualServer *vs = VisualServer::get_singleton(); | 
					
						
							|  |  |  | 			Bone *bonesptr = &bones[0]; | 
					
						
							|  |  |  | 			int len = bones.size(); | 
					
						
							|  |  |  | 			Transform global_transform = get_global_transform(); | 
					
						
							|  |  |  | 			Transform global_transform_inverse = global_transform.affine_inverse(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			for (int i = 0; i < len; i++) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				Bone &b = bonesptr[i]; | 
					
						
							|  |  |  | 				vs->skeleton_bone_set_transform(skeleton, i, global_transform * (b.transform_final * global_transform_inverse)); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		} break; | 
					
						
							|  |  |  | 		case NOTIFICATION_UPDATE_SKELETON: { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			VisualServer *vs = VisualServer::get_singleton(); | 
					
						
							|  |  |  | 			Bone *bonesptr = &bones[0]; | 
					
						
							|  |  |  | 			int len = bones.size(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			vs->skeleton_allocate(skeleton, len); // if same size, nothin really happens
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// pose changed, rebuild cache of inverses
 | 
					
						
							|  |  |  | 			if (rest_global_inverse_dirty) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// calculate global rests and invert them
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				for (int i = 0; i < len; i++) { | 
					
						
							|  |  |  | 					Bone &b = bonesptr[i]; | 
					
						
							|  |  |  | 					if (b.parent >= 0) | 
					
						
							|  |  |  | 						b.rest_global_inverse = bonesptr[b.parent].rest_global_inverse * b.rest; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 					else | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 						b.rest_global_inverse = b.rest; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				for (int i = 0; i < len; i++) { | 
					
						
							|  |  |  | 					Bone &b = bonesptr[i]; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 					b.rest_global_inverse.affine_invert(); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				rest_global_inverse_dirty = false; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-21 17:36:39 -03:00
										 |  |  | 			Transform global_transform = get_global_transform(); | 
					
						
							|  |  |  | 			Transform global_transform_inverse = global_transform.affine_inverse(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			for (int i = 0; i < len; i++) { | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				Bone &b = bonesptr[i]; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 				if (b.disable_rest) { | 
					
						
							|  |  |  | 					if (b.enabled) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 						Transform pose = b.pose; | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 						if (b.custom_pose_enable) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 							pose = b.custom_pose * pose; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 						if (b.parent >= 0) { | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 							b.pose_global = bonesptr[b.parent].pose_global * pose; | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 						} else { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 							b.pose_global = pose; | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 					} else { | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 						if (b.parent >= 0) { | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 							b.pose_global = bonesptr[b.parent].pose_global; | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 						} else { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 							b.pose_global = Transform(); | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				} else { | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 					if (b.enabled) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 						Transform pose = b.pose; | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 						if (b.custom_pose_enable) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							pose = b.custom_pose * pose; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 						if (b.parent >= 0) { | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 							b.pose_global = bonesptr[b.parent].pose_global * (b.rest * pose); | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 						} else { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 							b.pose_global = b.rest * pose; | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 					} else { | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 						if (b.parent >= 0) { | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 							b.pose_global = bonesptr[b.parent].pose_global * b.rest; | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 						} else { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 							b.pose_global = b.rest; | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-29 11:34:36 -03:00
										 |  |  | 				b.transform_final = b.pose_global * b.rest_global_inverse; | 
					
						
							|  |  |  | 				vs->skeleton_bone_set_transform(skeleton, i, global_transform * (b.transform_final * global_transform_inverse)); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				for (List<uint32_t>::Element *E = b.nodes_bound.front(); E; E = E->next()) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 					Object *obj = ObjectDB::get_instance(E->get()); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 					ERR_CONTINUE(!obj); | 
					
						
							| 
									
										
										
										
											2017-08-24 22:58:51 +02:00
										 |  |  | 					Spatial *sp = Object::cast_to<Spatial>(obj); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 					ERR_CONTINUE(!sp); | 
					
						
							| 
									
										
										
										
											2015-08-09 17:43:44 +01:00
										 |  |  | 					sp->set_transform(b.pose_global); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			dirty = false; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 		} break; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Transform Skeleton::get_bone_transform(int p_bone) const { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform()); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	if (dirty) | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		const_cast<Skeleton *>(this)->notification(NOTIFICATION_UPDATE_SKELETON); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return bones[p_bone].pose_global * bones[p_bone].rest_global_inverse; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void Skeleton::set_bone_global_pose(int p_bone, const Transform &p_pose) { | 
					
						
							| 
									
										
										
										
											2014-10-27 22:54:32 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX(p_bone, bones.size()); | 
					
						
							|  |  |  | 	if (bones[p_bone].parent == -1) { | 
					
						
							| 
									
										
										
										
											2014-10-27 22:54:32 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		set_bone_pose(p_bone, bones[p_bone].rest_global_inverse * p_pose); //fast
 | 
					
						
							| 
									
										
										
										
											2014-10-27 22:54:32 -03:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-05 21:20:42 -03:00
										 |  |  | 		set_bone_pose(p_bone, bones[p_bone].rest.affine_inverse() * (get_bone_global_pose(bones[p_bone].parent).affine_inverse() * p_pose)); //slow
 | 
					
						
							| 
									
										
										
										
											2014-10-27 22:54:32 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-14 10:31:38 -03:00
										 |  |  | Transform Skeleton::get_bone_global_pose(int p_bone) const { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform()); | 
					
						
							| 
									
										
										
										
											2014-08-14 10:31:38 -03:00
										 |  |  | 	if (dirty) | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		const_cast<Skeleton *>(this)->notification(NOTIFICATION_UPDATE_SKELETON); | 
					
						
							| 
									
										
										
										
											2014-08-14 10:31:38 -03:00
										 |  |  | 	return bones[p_bone].pose_global; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | RID Skeleton::get_skeleton() const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return skeleton; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // skeleton creation api
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void Skeleton::add_bone(const String &p_name) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_COND(p_name == "" || p_name.find(":") != -1 || p_name.find("/") != -1); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < bones.size(); i++) { | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		ERR_FAIL_COND(bones[i].name == "p_name"); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-23 10:35:05 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	Bone b; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	b.name = p_name; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	bones.push_back(b); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	rest_global_inverse_dirty = true; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	_make_dirty(); | 
					
						
							|  |  |  | 	update_gizmo(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | int Skeleton::find_bone(String p_name) const { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < bones.size(); i++) { | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		if (bones[i].name == p_name) | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			return i; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | String Skeleton::get_bone_name(int p_bone) const { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX_V(p_bone, bones.size(), ""); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return bones[p_bone].name; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int Skeleton::get_bone_count() const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return bones.size(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Skeleton::set_bone_parent(int p_bone, int p_parent) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX(p_bone, bones.size()); | 
					
						
							|  |  |  | 	ERR_FAIL_COND(p_parent != -1 && (p_parent < 0 || p_parent >= p_bone)); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	bones[p_bone].parent = p_parent; | 
					
						
							|  |  |  | 	rest_global_inverse_dirty = true; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	_make_dirty(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | void Skeleton::unparent_bone_and_rest(int p_bone) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX(p_bone, bones.size()); | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	int parent = bones[p_bone].parent; | 
					
						
							|  |  |  | 	while (parent >= 0) { | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 		bones[p_bone].rest = bones[parent].rest * bones[p_bone].rest; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		parent = bones[parent].parent; | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	bones[p_bone].parent = -1; | 
					
						
							|  |  |  | 	bones[p_bone].rest_global_inverse = bones[p_bone].rest.affine_inverse(); //same thing
 | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	_make_dirty(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Skeleton::set_bone_disable_rest(int p_bone, bool p_disable) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX(p_bone, bones.size()); | 
					
						
							|  |  |  | 	bones[p_bone].disable_rest = p_disable; | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Skeleton::is_bone_rest_disabled(int p_bone) const { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX_V(p_bone, bones.size(), false); | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 	return bones[p_bone].disable_rest; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | int Skeleton::get_bone_parent(int p_bone) const { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX_V(p_bone, bones.size(), -1); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return bones[p_bone].parent; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void Skeleton::set_bone_rest(int p_bone, const Transform &p_rest) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX(p_bone, bones.size()); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	bones[p_bone].rest = p_rest; | 
					
						
							|  |  |  | 	rest_global_inverse_dirty = true; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	_make_dirty(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | Transform Skeleton::get_bone_rest(int p_bone) const { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform()); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return bones[p_bone].rest; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Skeleton::set_bone_enabled(int p_bone, bool p_enabled) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX(p_bone, bones.size()); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	bones[p_bone].enabled = p_enabled; | 
					
						
							|  |  |  | 	rest_global_inverse_dirty = true; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	_make_dirty(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | bool Skeleton::is_bone_enabled(int p_bone) const { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX_V(p_bone, bones.size(), false); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return bones[p_bone].enabled; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void Skeleton::bind_child_node_to_bone(int p_bone, Node *p_node) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ERR_FAIL_NULL(p_node); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX(p_bone, bones.size()); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-07 17:17:31 +07:00
										 |  |  | 	uint32_t id = p_node->get_instance_id(); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (List<uint32_t>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) { | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		if (E->get() == id) | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			return; // already here
 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	bones[p_bone].nodes_bound.push_back(id); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void Skeleton::unbind_child_node_from_bone(int p_bone, Node *p_node) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ERR_FAIL_NULL(p_node); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX(p_bone, bones.size()); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-07 17:17:31 +07:00
										 |  |  | 	uint32_t id = p_node->get_instance_id(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	bones[p_bone].nodes_bound.erase(id); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void Skeleton::get_bound_child_nodes_to_bone(int p_bone, List<Node *> *p_bound) const { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX(p_bone, bones.size()); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (const List<uint32_t>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) { | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		Object *obj = ObjectDB::get_instance(E->get()); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		ERR_CONTINUE(!obj); | 
					
						
							| 
									
										
										
										
											2017-08-24 22:58:51 +02:00
										 |  |  | 		p_bound->push_back(Object::cast_to<Node>(obj)); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Skeleton::clear_bones() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bones.clear(); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	rest_global_inverse_dirty = true; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	_make_dirty(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // posing api
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void Skeleton::set_bone_pose(int p_bone, const Transform &p_pose) { | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX(p_bone, bones.size()); | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!is_inside_tree()); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	bones[p_bone].pose = p_pose; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	_make_dirty(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | Transform Skeleton::get_bone_pose(int p_bone) const { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform()); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return bones[p_bone].pose; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void Skeleton::set_bone_custom_pose(int p_bone, const Transform &p_custom_pose) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX(p_bone, bones.size()); | 
					
						
							| 
									
										
										
										
											2017-01-14 12:26:56 +01:00
										 |  |  | 	//ERR_FAIL_COND( !is_inside_scene() );
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	bones[p_bone].custom_pose_enable = (p_custom_pose != Transform()); | 
					
						
							|  |  |  | 	bones[p_bone].custom_pose = p_custom_pose; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	_make_dirty(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Transform Skeleton::get_bone_custom_pose(int p_bone) const { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform()); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return bones[p_bone].custom_pose; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Skeleton::_make_dirty() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (dirty) | 
					
						
							|  |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-05 21:20:42 -03:00
										 |  |  | 	if (!is_inside_tree()) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		dirty = true; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	MessageQueue::get_singleton()->push_notification(this, NOTIFICATION_UPDATE_SKELETON); | 
					
						
							|  |  |  | 	dirty = true; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Skeleton::localize_rests() { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = bones.size() - 1; i >= 0; i--) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		if (bones[i].parent >= 0) | 
					
						
							|  |  |  | 			set_bone_rest(i, bones[bones[i].parent].rest.affine_inverse() * bones[i].rest); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Skeleton::_bind_methods() { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("add_bone", "name"), &Skeleton::add_bone); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("find_bone", "name"), &Skeleton::find_bone); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_bone_name", "bone_idx"), &Skeleton::get_bone_name); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_bone_parent", "bone_idx"), &Skeleton::get_bone_parent); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_bone_parent", "bone_idx", "parent_idx"), &Skeleton::set_bone_parent); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_bone_count"), &Skeleton::get_bone_count); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("unparent_bone_and_rest", "bone_idx"), &Skeleton::unparent_bone_and_rest); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_bone_rest", "bone_idx"), &Skeleton::get_bone_rest); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_bone_rest", "bone_idx", "rest"), &Skeleton::set_bone_rest); | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("set_bone_disable_rest", "bone_idx", "disable"), &Skeleton::set_bone_disable_rest); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("is_bone_rest_disabled", "bone_idx"), &Skeleton::is_bone_rest_disabled); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-09 13:19:41 +02:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("bind_child_node_to_bone", "bone_idx", "node"), &Skeleton::bind_child_node_to_bone); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("unbind_child_node_from_bone", "bone_idx", "node"), &Skeleton::unbind_child_node_from_bone); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_bound_child_nodes_to_bone", "bone_idx"), &Skeleton::_get_bound_child_nodes_to_bone); | 
					
						
							| 
									
										
										
										
											2015-09-24 18:06:15 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("clear_bones"), &Skeleton::clear_bones); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_bone_pose", "bone_idx"), &Skeleton::get_bone_pose); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_bone_pose", "bone_idx", "pose"), &Skeleton::set_bone_pose); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("set_bone_global_pose", "bone_idx", "pose"), &Skeleton::set_bone_global_pose); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_bone_global_pose", "bone_idx"), &Skeleton::get_bone_global_pose); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_bone_custom_pose", "bone_idx"), &Skeleton::get_bone_custom_pose); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_bone_custom_pose", "bone_idx", "custom_pose"), &Skeleton::set_bone_custom_pose); | 
					
						
							| 
									
										
										
										
											2014-08-14 10:31:38 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_bone_transform", "bone_idx"), &Skeleton::get_bone_transform); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	BIND_CONSTANT(NOTIFICATION_UPDATE_SKELETON); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Skeleton::Skeleton() { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	rest_global_inverse_dirty = true; | 
					
						
							|  |  |  | 	dirty = false; | 
					
						
							|  |  |  | 	skeleton = VisualServer::get_singleton()->skeleton_create(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Skeleton::~Skeleton() { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	VisualServer::get_singleton()->free(skeleton); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } |