| 1 | /**************************************************************************/ |
| 2 | /* animation_blend_space_1d.cpp */ |
| 3 | /**************************************************************************/ |
| 4 | /* This file is part of: */ |
| 5 | /* GODOT ENGINE */ |
| 6 | /* https://godotengine.org */ |
| 7 | /**************************************************************************/ |
| 8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
| 9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
| 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 | |
| 31 | #include "animation_blend_space_1d.h" |
| 32 | |
| 33 | #include "animation_blend_tree.h" |
| 34 | |
| 35 | void AnimationNodeBlendSpace1D::get_parameter_list(List<PropertyInfo> *r_list) const { |
| 36 | r_list->push_back(PropertyInfo(Variant::FLOAT, blend_position)); |
| 37 | r_list->push_back(PropertyInfo(Variant::INT, closest, PROPERTY_HINT_NONE, "" , PROPERTY_USAGE_NONE)); |
| 38 | r_list->push_back(PropertyInfo(Variant::FLOAT, length_internal, PROPERTY_HINT_NONE, "" , PROPERTY_USAGE_NONE)); |
| 39 | } |
| 40 | |
| 41 | Variant AnimationNodeBlendSpace1D::get_parameter_default_value(const StringName &p_parameter) const { |
| 42 | if (p_parameter == closest) { |
| 43 | return -1; |
| 44 | } else { |
| 45 | return 0; |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | Ref<AnimationNode> AnimationNodeBlendSpace1D::get_child_by_name(const StringName &p_name) const { |
| 50 | return get_blend_point_node(p_name.operator String().to_int()); |
| 51 | } |
| 52 | |
| 53 | void AnimationNodeBlendSpace1D::_validate_property(PropertyInfo &p_property) const { |
| 54 | if (p_property.name.begins_with("blend_point_" )) { |
| 55 | String left = p_property.name.get_slicec('/', 0); |
| 56 | int idx = left.get_slicec('_', 2).to_int(); |
| 57 | if (idx >= blend_points_used) { |
| 58 | p_property.usage = PROPERTY_USAGE_NONE; |
| 59 | } |
| 60 | } |
| 61 | } |
| 62 | |
| 63 | void AnimationNodeBlendSpace1D::_tree_changed() { |
| 64 | AnimationRootNode::_tree_changed(); |
| 65 | } |
| 66 | |
| 67 | void AnimationNodeBlendSpace1D::_animation_node_renamed(const ObjectID &p_oid, const String &p_old_name, const String &p_new_name) { |
| 68 | AnimationRootNode::_animation_node_renamed(p_oid, p_old_name, p_new_name); |
| 69 | } |
| 70 | |
| 71 | void AnimationNodeBlendSpace1D::_animation_node_removed(const ObjectID &p_oid, const StringName &p_node) { |
| 72 | AnimationRootNode::_animation_node_removed(p_oid, p_node); |
| 73 | } |
| 74 | |
| 75 | void AnimationNodeBlendSpace1D::_bind_methods() { |
| 76 | ClassDB::bind_method(D_METHOD("add_blend_point" , "node" , "pos" , "at_index" ), &AnimationNodeBlendSpace1D::add_blend_point, DEFVAL(-1)); |
| 77 | ClassDB::bind_method(D_METHOD("set_blend_point_position" , "point" , "pos" ), &AnimationNodeBlendSpace1D::set_blend_point_position); |
| 78 | ClassDB::bind_method(D_METHOD("get_blend_point_position" , "point" ), &AnimationNodeBlendSpace1D::get_blend_point_position); |
| 79 | ClassDB::bind_method(D_METHOD("set_blend_point_node" , "point" , "node" ), &AnimationNodeBlendSpace1D::set_blend_point_node); |
| 80 | ClassDB::bind_method(D_METHOD("get_blend_point_node" , "point" ), &AnimationNodeBlendSpace1D::get_blend_point_node); |
| 81 | ClassDB::bind_method(D_METHOD("remove_blend_point" , "point" ), &AnimationNodeBlendSpace1D::remove_blend_point); |
| 82 | ClassDB::bind_method(D_METHOD("get_blend_point_count" ), &AnimationNodeBlendSpace1D::get_blend_point_count); |
| 83 | |
| 84 | ClassDB::bind_method(D_METHOD("set_min_space" , "min_space" ), &AnimationNodeBlendSpace1D::set_min_space); |
| 85 | ClassDB::bind_method(D_METHOD("get_min_space" ), &AnimationNodeBlendSpace1D::get_min_space); |
| 86 | |
| 87 | ClassDB::bind_method(D_METHOD("set_max_space" , "max_space" ), &AnimationNodeBlendSpace1D::set_max_space); |
| 88 | ClassDB::bind_method(D_METHOD("get_max_space" ), &AnimationNodeBlendSpace1D::get_max_space); |
| 89 | |
| 90 | ClassDB::bind_method(D_METHOD("set_snap" , "snap" ), &AnimationNodeBlendSpace1D::set_snap); |
| 91 | ClassDB::bind_method(D_METHOD("get_snap" ), &AnimationNodeBlendSpace1D::get_snap); |
| 92 | |
| 93 | ClassDB::bind_method(D_METHOD("set_value_label" , "text" ), &AnimationNodeBlendSpace1D::set_value_label); |
| 94 | ClassDB::bind_method(D_METHOD("get_value_label" ), &AnimationNodeBlendSpace1D::get_value_label); |
| 95 | |
| 96 | ClassDB::bind_method(D_METHOD("set_blend_mode" , "mode" ), &AnimationNodeBlendSpace1D::set_blend_mode); |
| 97 | ClassDB::bind_method(D_METHOD("get_blend_mode" ), &AnimationNodeBlendSpace1D::get_blend_mode); |
| 98 | |
| 99 | ClassDB::bind_method(D_METHOD("set_use_sync" , "enable" ), &AnimationNodeBlendSpace1D::set_use_sync); |
| 100 | ClassDB::bind_method(D_METHOD("is_using_sync" ), &AnimationNodeBlendSpace1D::is_using_sync); |
| 101 | |
| 102 | ClassDB::bind_method(D_METHOD("_add_blend_point" , "index" , "node" ), &AnimationNodeBlendSpace1D::_add_blend_point); |
| 103 | |
| 104 | for (int i = 0; i < MAX_BLEND_POINTS; i++) { |
| 105 | ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "blend_point_" + itos(i) + "/node" , PROPERTY_HINT_RESOURCE_TYPE, "AnimationRootNode" , PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_add_blend_point" , "get_blend_point_node" , i); |
| 106 | ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "blend_point_" + itos(i) + "/pos" , PROPERTY_HINT_NONE, "" , PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_blend_point_position" , "get_blend_point_position" , i); |
| 107 | } |
| 108 | |
| 109 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "min_space" , PROPERTY_HINT_NONE, "" , PROPERTY_USAGE_NO_EDITOR), "set_min_space" , "get_min_space" ); |
| 110 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_space" , PROPERTY_HINT_NONE, "" , PROPERTY_USAGE_NO_EDITOR), "set_max_space" , "get_max_space" ); |
| 111 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "snap" , PROPERTY_HINT_NONE, "" , PROPERTY_USAGE_NO_EDITOR), "set_snap" , "get_snap" ); |
| 112 | ADD_PROPERTY(PropertyInfo(Variant::STRING, "value_label" , PROPERTY_HINT_NONE, "" , PROPERTY_USAGE_NO_EDITOR), "set_value_label" , "get_value_label" ); |
| 113 | ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode" , PROPERTY_HINT_ENUM, "Interpolated,Discrete,Carry" , PROPERTY_USAGE_NO_EDITOR), "set_blend_mode" , "get_blend_mode" ); |
| 114 | ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync" , PROPERTY_HINT_NONE, "" , PROPERTY_USAGE_NO_EDITOR), "set_use_sync" , "is_using_sync" ); |
| 115 | |
| 116 | BIND_ENUM_CONSTANT(BLEND_MODE_INTERPOLATED); |
| 117 | BIND_ENUM_CONSTANT(BLEND_MODE_DISCRETE); |
| 118 | BIND_ENUM_CONSTANT(BLEND_MODE_DISCRETE_CARRY); |
| 119 | } |
| 120 | |
| 121 | void AnimationNodeBlendSpace1D::get_child_nodes(List<ChildNode> *r_child_nodes) { |
| 122 | for (int i = 0; i < blend_points_used; i++) { |
| 123 | ChildNode cn; |
| 124 | cn.name = itos(i); |
| 125 | cn.node = blend_points[i].node; |
| 126 | r_child_nodes->push_back(cn); |
| 127 | } |
| 128 | } |
| 129 | |
| 130 | void AnimationNodeBlendSpace1D::add_blend_point(const Ref<AnimationRootNode> &p_node, float p_position, int p_at_index) { |
| 131 | ERR_FAIL_COND(blend_points_used >= MAX_BLEND_POINTS); |
| 132 | ERR_FAIL_COND(p_node.is_null()); |
| 133 | |
| 134 | ERR_FAIL_COND(p_at_index < -1 || p_at_index > blend_points_used); |
| 135 | |
| 136 | if (p_at_index == -1 || p_at_index == blend_points_used) { |
| 137 | p_at_index = blend_points_used; |
| 138 | } else { |
| 139 | for (int i = blend_points_used - 1; i > p_at_index; i--) { |
| 140 | blend_points[i] = blend_points[i - 1]; |
| 141 | } |
| 142 | } |
| 143 | |
| 144 | blend_points[p_at_index].node = p_node; |
| 145 | blend_points[p_at_index].position = p_position; |
| 146 | |
| 147 | blend_points[p_at_index].node->connect("tree_changed" , callable_mp(this, &AnimationNodeBlendSpace1D::_tree_changed), CONNECT_REFERENCE_COUNTED); |
| 148 | blend_points[p_at_index].node->connect("animation_node_renamed" , callable_mp(this, &AnimationNodeBlendSpace1D::_animation_node_renamed), CONNECT_REFERENCE_COUNTED); |
| 149 | blend_points[p_at_index].node->connect("animation_node_removed" , callable_mp(this, &AnimationNodeBlendSpace1D::_animation_node_removed), CONNECT_REFERENCE_COUNTED); |
| 150 | |
| 151 | blend_points_used++; |
| 152 | emit_signal(SNAME("tree_changed" )); |
| 153 | } |
| 154 | |
| 155 | void AnimationNodeBlendSpace1D::set_blend_point_position(int p_point, float p_position) { |
| 156 | ERR_FAIL_INDEX(p_point, blend_points_used); |
| 157 | |
| 158 | blend_points[p_point].position = p_position; |
| 159 | } |
| 160 | |
| 161 | void AnimationNodeBlendSpace1D::set_blend_point_node(int p_point, const Ref<AnimationRootNode> &p_node) { |
| 162 | ERR_FAIL_INDEX(p_point, blend_points_used); |
| 163 | ERR_FAIL_COND(p_node.is_null()); |
| 164 | |
| 165 | if (blend_points[p_point].node.is_valid()) { |
| 166 | blend_points[p_point].node->disconnect("tree_changed" , callable_mp(this, &AnimationNodeBlendSpace1D::_tree_changed)); |
| 167 | blend_points[p_point].node->disconnect("animation_node_renamed" , callable_mp(this, &AnimationNodeBlendSpace1D::_animation_node_renamed)); |
| 168 | blend_points[p_point].node->disconnect("animation_node_removed" , callable_mp(this, &AnimationNodeBlendSpace1D::_animation_node_removed)); |
| 169 | } |
| 170 | |
| 171 | blend_points[p_point].node = p_node; |
| 172 | blend_points[p_point].node->connect("tree_changed" , callable_mp(this, &AnimationNodeBlendSpace1D::_tree_changed), CONNECT_REFERENCE_COUNTED); |
| 173 | blend_points[p_point].node->connect("animation_node_renamed" , callable_mp(this, &AnimationNodeBlendSpace1D::_animation_node_renamed), CONNECT_REFERENCE_COUNTED); |
| 174 | blend_points[p_point].node->connect("animation_node_removed" , callable_mp(this, &AnimationNodeBlendSpace1D::_animation_node_removed), CONNECT_REFERENCE_COUNTED); |
| 175 | |
| 176 | emit_signal(SNAME("tree_changed" )); |
| 177 | } |
| 178 | |
| 179 | float AnimationNodeBlendSpace1D::get_blend_point_position(int p_point) const { |
| 180 | ERR_FAIL_INDEX_V(p_point, blend_points_used, 0); |
| 181 | return blend_points[p_point].position; |
| 182 | } |
| 183 | |
| 184 | Ref<AnimationRootNode> AnimationNodeBlendSpace1D::get_blend_point_node(int p_point) const { |
| 185 | ERR_FAIL_INDEX_V(p_point, blend_points_used, Ref<AnimationRootNode>()); |
| 186 | return blend_points[p_point].node; |
| 187 | } |
| 188 | |
| 189 | void AnimationNodeBlendSpace1D::remove_blend_point(int p_point) { |
| 190 | ERR_FAIL_INDEX(p_point, blend_points_used); |
| 191 | |
| 192 | ERR_FAIL_COND(blend_points[p_point].node.is_null()); |
| 193 | blend_points[p_point].node->disconnect("tree_changed" , callable_mp(this, &AnimationNodeBlendSpace1D::_tree_changed)); |
| 194 | blend_points[p_point].node->disconnect("animation_node_renamed" , callable_mp(this, &AnimationNodeBlendSpace1D::_animation_node_renamed)); |
| 195 | blend_points[p_point].node->disconnect("animation_node_removed" , callable_mp(this, &AnimationNodeBlendSpace1D::_animation_node_removed)); |
| 196 | |
| 197 | for (int i = p_point; i < blend_points_used - 1; i++) { |
| 198 | blend_points[i] = blend_points[i + 1]; |
| 199 | } |
| 200 | |
| 201 | blend_points_used--; |
| 202 | |
| 203 | emit_signal(SNAME("animation_node_removed" ), get_instance_id(), itos(p_point)); |
| 204 | emit_signal(SNAME("tree_changed" )); |
| 205 | } |
| 206 | |
| 207 | int AnimationNodeBlendSpace1D::get_blend_point_count() const { |
| 208 | return blend_points_used; |
| 209 | } |
| 210 | |
| 211 | void AnimationNodeBlendSpace1D::set_min_space(float p_min) { |
| 212 | min_space = p_min; |
| 213 | |
| 214 | if (min_space >= max_space) { |
| 215 | min_space = max_space - 1; |
| 216 | } |
| 217 | } |
| 218 | |
| 219 | float AnimationNodeBlendSpace1D::get_min_space() const { |
| 220 | return min_space; |
| 221 | } |
| 222 | |
| 223 | void AnimationNodeBlendSpace1D::set_max_space(float p_max) { |
| 224 | max_space = p_max; |
| 225 | |
| 226 | if (max_space <= min_space) { |
| 227 | max_space = min_space + 1; |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | float AnimationNodeBlendSpace1D::get_max_space() const { |
| 232 | return max_space; |
| 233 | } |
| 234 | |
| 235 | void AnimationNodeBlendSpace1D::set_snap(float p_snap) { |
| 236 | snap = p_snap; |
| 237 | } |
| 238 | |
| 239 | float AnimationNodeBlendSpace1D::get_snap() const { |
| 240 | return snap; |
| 241 | } |
| 242 | |
| 243 | void AnimationNodeBlendSpace1D::set_value_label(const String &p_label) { |
| 244 | value_label = p_label; |
| 245 | } |
| 246 | |
| 247 | String AnimationNodeBlendSpace1D::get_value_label() const { |
| 248 | return value_label; |
| 249 | } |
| 250 | |
| 251 | void AnimationNodeBlendSpace1D::set_blend_mode(BlendMode p_blend_mode) { |
| 252 | blend_mode = p_blend_mode; |
| 253 | } |
| 254 | |
| 255 | AnimationNodeBlendSpace1D::BlendMode AnimationNodeBlendSpace1D::get_blend_mode() const { |
| 256 | return blend_mode; |
| 257 | } |
| 258 | |
| 259 | void AnimationNodeBlendSpace1D::set_use_sync(bool p_sync) { |
| 260 | sync = p_sync; |
| 261 | } |
| 262 | |
| 263 | bool AnimationNodeBlendSpace1D::is_using_sync() const { |
| 264 | return sync; |
| 265 | } |
| 266 | |
| 267 | void AnimationNodeBlendSpace1D::_add_blend_point(int p_index, const Ref<AnimationRootNode> &p_node) { |
| 268 | if (p_index == blend_points_used) { |
| 269 | add_blend_point(p_node, 0); |
| 270 | } else { |
| 271 | set_blend_point_node(p_index, p_node); |
| 272 | } |
| 273 | } |
| 274 | |
| 275 | double AnimationNodeBlendSpace1D::_process(double p_time, bool p_seek, bool p_is_external_seeking, bool p_test_only) { |
| 276 | if (blend_points_used == 0) { |
| 277 | return 0.0; |
| 278 | } |
| 279 | |
| 280 | if (blend_points_used == 1) { |
| 281 | // only one point available, just play that animation |
| 282 | return blend_node(blend_points[0].name, blend_points[0].node, p_time, p_seek, p_is_external_seeking, 1.0, FILTER_IGNORE, true, p_test_only); |
| 283 | } |
| 284 | |
| 285 | double blend_pos = get_parameter(blend_position); |
| 286 | int cur_closest = get_parameter(closest); |
| 287 | double cur_length_internal = get_parameter(length_internal); |
| 288 | double max_time_remaining = 0.0; |
| 289 | |
| 290 | if (blend_mode == BLEND_MODE_INTERPOLATED) { |
| 291 | int point_lower = -1; |
| 292 | float pos_lower = 0.0; |
| 293 | int point_higher = -1; |
| 294 | float pos_higher = 0.0; |
| 295 | |
| 296 | // find the closest two points to blend between |
| 297 | for (int i = 0; i < blend_points_used; i++) { |
| 298 | float pos = blend_points[i].position; |
| 299 | |
| 300 | if (pos <= blend_pos) { |
| 301 | if (point_lower == -1 || pos > pos_lower) { |
| 302 | point_lower = i; |
| 303 | pos_lower = pos; |
| 304 | } |
| 305 | } else if (point_higher == -1 || pos < pos_higher) { |
| 306 | point_higher = i; |
| 307 | pos_higher = pos; |
| 308 | } |
| 309 | } |
| 310 | |
| 311 | // fill in weights |
| 312 | float weights[MAX_BLEND_POINTS] = {}; |
| 313 | if (point_lower == -1 && point_higher != -1) { |
| 314 | // we are on the left side, no other point to the left |
| 315 | // we just play the next point. |
| 316 | |
| 317 | weights[point_higher] = 1.0; |
| 318 | } else if (point_higher == -1) { |
| 319 | // we are on the right side, no other point to the right |
| 320 | // we just play the previous point |
| 321 | |
| 322 | weights[point_lower] = 1.0; |
| 323 | } else { |
| 324 | // we are between two points. |
| 325 | // figure out weights, then blend the animations |
| 326 | |
| 327 | float distance_between_points = pos_higher - pos_lower; |
| 328 | |
| 329 | float current_pos_inbetween = blend_pos - pos_lower; |
| 330 | |
| 331 | float blend_percentage = current_pos_inbetween / distance_between_points; |
| 332 | |
| 333 | float blend_lower = 1.0 - blend_percentage; |
| 334 | float blend_higher = blend_percentage; |
| 335 | |
| 336 | weights[point_lower] = blend_lower; |
| 337 | weights[point_higher] = blend_higher; |
| 338 | } |
| 339 | |
| 340 | // actually blend the animations now |
| 341 | |
| 342 | for (int i = 0; i < blend_points_used; i++) { |
| 343 | if (i == point_lower || i == point_higher) { |
| 344 | double remaining = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_is_external_seeking, weights[i], FILTER_IGNORE, true, p_test_only); |
| 345 | max_time_remaining = MAX(max_time_remaining, remaining); |
| 346 | } else if (sync) { |
| 347 | blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_is_external_seeking, 0, FILTER_IGNORE, true, p_test_only); |
| 348 | } |
| 349 | } |
| 350 | } else { |
| 351 | int new_closest = -1; |
| 352 | double new_closest_dist = 1e20; |
| 353 | |
| 354 | for (int i = 0; i < blend_points_used; i++) { |
| 355 | double d = abs(blend_points[i].position - blend_pos); |
| 356 | if (d < new_closest_dist) { |
| 357 | new_closest = i; |
| 358 | new_closest_dist = d; |
| 359 | } |
| 360 | } |
| 361 | |
| 362 | if (new_closest != cur_closest && new_closest != -1) { |
| 363 | double from = 0.0; |
| 364 | if (blend_mode == BLEND_MODE_DISCRETE_CARRY && cur_closest != -1) { |
| 365 | //for ping-pong loop |
| 366 | Ref<AnimationNodeAnimation> na_c = static_cast<Ref<AnimationNodeAnimation>>(blend_points[cur_closest].node); |
| 367 | Ref<AnimationNodeAnimation> na_n = static_cast<Ref<AnimationNodeAnimation>>(blend_points[new_closest].node); |
| 368 | if (!na_c.is_null() && !na_n.is_null()) { |
| 369 | na_n->set_backward(na_c->is_backward()); |
| 370 | } |
| 371 | //see how much animation remains |
| 372 | from = cur_length_internal - blend_node(blend_points[cur_closest].name, blend_points[cur_closest].node, p_time, false, p_is_external_seeking, 0.0, FILTER_IGNORE, true, p_test_only); |
| 373 | } |
| 374 | |
| 375 | max_time_remaining = blend_node(blend_points[new_closest].name, blend_points[new_closest].node, from, true, p_is_external_seeking, 1.0, FILTER_IGNORE, true, p_test_only); |
| 376 | cur_length_internal = from + max_time_remaining; |
| 377 | |
| 378 | cur_closest = new_closest; |
| 379 | |
| 380 | } else { |
| 381 | max_time_remaining = blend_node(blend_points[cur_closest].name, blend_points[cur_closest].node, p_time, p_seek, p_is_external_seeking, 1.0, FILTER_IGNORE, true, p_test_only); |
| 382 | } |
| 383 | |
| 384 | if (sync) { |
| 385 | for (int i = 0; i < blend_points_used; i++) { |
| 386 | if (i != cur_closest) { |
| 387 | blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_is_external_seeking, 0, FILTER_IGNORE, true, p_test_only); |
| 388 | } |
| 389 | } |
| 390 | } |
| 391 | } |
| 392 | |
| 393 | set_parameter(this->closest, cur_closest); |
| 394 | set_parameter(this->length_internal, cur_length_internal); |
| 395 | return max_time_remaining; |
| 396 | } |
| 397 | |
| 398 | String AnimationNodeBlendSpace1D::get_caption() const { |
| 399 | return "BlendSpace1D" ; |
| 400 | } |
| 401 | |
| 402 | AnimationNodeBlendSpace1D::AnimationNodeBlendSpace1D() { |
| 403 | for (int i = 0; i < MAX_BLEND_POINTS; i++) { |
| 404 | blend_points[i].name = itos(i); |
| 405 | } |
| 406 | } |
| 407 | |
| 408 | AnimationNodeBlendSpace1D::~AnimationNodeBlendSpace1D() { |
| 409 | } |
| 410 | |